Python · Синтаксис · Начальный уровень

Методы списков и кортежей

10 задач

Освойте все методы списков и разберитесь в ключевых отличиях между списками и кортежами.

Методы списков

#
Список — это упорядоченная **мутабельная** последовательность: её можно изменять после создания. Python предоставляет набор методов, которые модифицируют список непосредственно (in-place). ## Добавление элементов ```python fruits = ["apple", "banana"] fruits.append("cherry") # добавить один элемент в конец print(fruits) # ["apple", "banana", "cherry"] fruits.extend(["date", "elderberry"]) # добавить все элементы из итерируемого print(fruits) # ["apple", "banana", "cherry", "date", "elderberry"] fruits.insert(1, "avocado") # вставить на индекс 1 print(fruits) # ["apple", "avocado", "banana", "cherry", "date", "elderberry"] ``` **Ключевое отличие**: `append(x)` добавляет `x` как один элемент; `extend(iterable)` распаковывает и добавляет каждый элемент отдельно. `list.append([1,2])` даст `[..., [1,2]]`, а `list.extend([1,2])` — `[..., 1, 2]`. ## Удаление элементов ```python nums = [1, 2, 3, 2, 4] nums.remove(2) # удаляет ПЕРВОЕ вхождение значения 2 print(nums) # [1, 3, 2, 4] popped = nums.pop() # удаляет и возвращает ПОСЛЕДНИЙ элемент print(popped) # 4 print(nums) # [1, 3, 2] popped = nums.pop(0) # удаляет и возвращает элемент по индексу 0 print(popped) # 1 print(nums) # [3, 2] nums.clear() # удаляет все элементы print(nums) # [] ``` ## Поиск ```python items = ["a", "b", "c", "b"] print(items.index("b")) # 1 — индекс ПЕРВОГО совпадения (кидает ValueError если нет) print(items.count("b")) # 2 — количество всех совпадений print("c" in items) # True — `in` для проверки наличия ``` ## Сортировка и разворот ```python nums = [3, 1, 4, 1, 5, 9, 2, 6] nums.sort() # сортирует на месте, по возрастанию print(nums) # [1, 1, 2, 3, 4, 5, 6, 9] nums.sort(reverse=True) # сортирует на месте, по убыванию print(nums) # [9, 6, 5, 4, 3, 2, 1, 1] words = ["banana", "apple", "cherry"] words.sort(key=len) # сортировать по длине строки print(words) # ["apple", "banana", "cherry"] nums.reverse() # разворачивает на месте (не сортирует) ``` `sort()` модифицирует список и возвращает `None`. Используйте `sorted(lst)`, если нужен новый отсортированный список без изменения оригинала. ## Копирование ```python original = [1, 2, 3] copy1 = original.copy() # поверхностная копия copy2 = original[:] # тоже поверхностная копия copy1.append(99) print(original) # [1, 2, 3] — не изменился print(copy1) # [1, 2, 3, 99] ``` Никогда не делайте `copy = original` — это создаёт **псевдоним**, а не копию.

Кортежи и распаковка

#
Кортеж — это упорядоченная **неизменяемая** последовательность. После создания содержимое изменить нельзя. Используйте кортежи для данных, которые не должны меняться. ## Основы кортежей ```python point = (3, 7) rgb = (255, 128, 0) single = (42,) # кортеж из одного элемента — обратите внимание на запятую! empty = () print(type(point)) # <class 'tuple'> print(point[0]) # 3 print(len(rgb)) # 3 ``` Кортеж без скобок тоже работает: ```python coords = 10, 20 # то же, что (10, 20) ``` ## List vs Tuple: когда что использовать | Список `[]` | Кортеж `()` | |---|---| | Мутабельный — можно добавлять/удалять/изменять | Неизменяемый — фиксирован после создания | | Для коллекций, которые растут/уменьшаются | Для фиксированных записей (координаты, RGB, строки БД) | | Чуть больше памяти | Чуть быстрее доступ, меньше памяти | | Нельзя использовать как ключ словаря | Можно использовать как ключ словаря | ```python # Список: растущая коллекция shopping = [] shopping.append("milk") shopping.append("eggs") # Кортеж: фиксированная запись person = ("Alice", 30, "engineer") name, age, role = person # распаковка ``` ## Распаковка кортежей ```python x, y = (10, 20) print(x) # 10 print(y) # 20 # Обмен переменных без временной переменной a, b = 1, 2 a, b = b, a print(a, b) # 2 1 # Расширенная распаковка first, *rest = [1, 2, 3, 4, 5] print(first) # 1 print(rest) # [2, 3, 4, 5] *start, last = [1, 2, 3, 4, 5] print(start) # [1, 2, 3, 4] print(last) # 5 ``` ## Кортежи в циклах ```python pairs = [(1, "one"), (2, "two"), (3, "three")] for number, word in pairs: print(f"{number} = {word}") # 1 = one # 2 = two # 3 = three ``` Именно так работают `enumerate()` и `dict.items()` — они возвращают кортежи. ## Возврат нескольких значений из функции ```python def min_max(numbers): return min(numbers), max(numbers) # возвращает кортеж lo, hi = min_max([3, 1, 4, 1, 5, 9]) print(lo, hi) # 1 9 ``` Функции, возвращающие несколько значений, всегда возвращают кортеж. Распаковка — идиоматический способ их получить.

Справочник: методы списков и кортежей

#
## Методы списков | Метод | Что делает | Возвращает | |---|---|---| | `lst.append(x)` | Добавить `x` в конец | `None` | | `lst.extend(iterable)` | Добавить все элементы из iterable | `None` | | `lst.insert(i, x)` | Вставить `x` на индекс `i` | `None` | | `lst.pop()` | Удалить и вернуть последний элемент | элемент | | `lst.pop(i)` | Удалить и вернуть элемент по индексу `i` | элемент | | `lst.remove(x)` | Удалить первое вхождение `x` | `None` | | `lst.clear()` | Удалить все элементы | `None` | | `lst.index(x)` | Индекс первого `x` (кидает ValueError) | int | | `lst.count(x)` | Количество вхождений `x` | int | | `lst.sort(key=None, reverse=False)` | Сортировать на месте | `None` | | `lst.reverse()` | Развернуть на месте | `None` | | `lst.copy()` | Поверхностная копия | новый список | ## Встроенные функции для списков | Функция | Что делает | |---|---| | `sorted(lst, key=None, reverse=False)` | Возвращает новый отсортированный список | | `reversed(lst)` | Возвращает обратный итератор | | `len(lst)` | Количество элементов | | `min(lst)` / `max(lst)` | Минимум / максимум | | `sum(lst)` | Сумма числовых элементов | | `list(iterable)` | Конвертировать в список | ## Операции с кортежами | Операция | Пример | Результат | |---|---|---| | Создать | `t = (1, 2, 3)` | — | | Доступ | `t[0]` | `1` | | Срез | `t[1:]` | `(2, 3)` | | Распаковка | `a, b, c = t` | a=1, b=2, c=3 | | Звёздочная распаковка | `first, *rest = t` | first=1, rest=[2,3] | | Конкатенация | `(1, 2) + (3, 4)` | `(1, 2, 3, 4)` | | Повторение | `(0,) * 3` | `(0, 0, 0)` | | `len(t)` | `len((1, 2, 3))` | `3` | | `x in t` | `2 in (1, 2, 3)` | `True` | | Конвертация | `list(t)` / `tuple(lst)` | — | ## append vs extend ```python lst = [1, 2] lst.append([3, 4]) # → [1, 2, [3, 4]] ← список как один элемент lst = [1, 2] lst.extend([3, 4]) # → [1, 2, 3, 4] ← элементы добавляются по отдельности ``` ## sort vs sorted ```python nums = [3, 1, 2] nums.sort() # модифицирует nums на месте, возвращает None print(nums) # [1, 2, 3] nums = [3, 1, 2] new = sorted(nums) # возвращает новый список, nums не изменяется print(nums, new) # [3, 1, 2] [1, 2, 3] ```
01

append vs extend

#

У вас есть список `result = [1, 2, 3]`. Напишите два отдельных выражения: 1. Используйте `append`, чтобы добавить список `[4, 5]` как один элемент. 2. Начиная заново от `[1, 2, 3]`, используйте `extend`, чтобы добавить `[4, 5]` как отдельные элементы. Выведите оба результата и объясните разницу.

result = [1, 2, 3]

# 1. Используйте append, чтобы добавить [4, 5] как ОДИН элемент


# 2. Начните заново и используйте extend, чтобы добавить [4, 5] как ОТДЕЛЬНЫЕ элементы
result2 = [1, 2, 3]
Решение
result = [1, 2, 3]
result.append([4, 5])
print(result)   # [1, 2, 3, [4, 5]]  — вложенный список

result2 = [1, 2, 3]
result2.extend([4, 5])
print(result2)  # [1, 2, 3, 4, 5]   — отдельные элементы
02

Вставка на позицию

#

Напишите функцию `insert_after(lst, target, value)`, которая вставляет `value` сразу после первого вхождения `target` в `lst`. Если `target` не найден, добавьте `value` в конец. Пример: `insert_after([1, 2, 4, 5], 2, 3)` → `[1, 2, 3, 4, 5]`.

def insert_after(lst, target, value):
    pass


print(insert_after([1, 2, 4, 5], 2, 3))    # [1, 2, 3, 4, 5]
print(insert_after([1, 2, 3], 99, 0))       # [1, 2, 3, 0]
Решение
def insert_after(lst, target, value):
    result = lst[:]
    if target in result:
        idx = result.index(target)
        result.insert(idx + 1, value)
    else:
        result.append(value)
    return result


print(insert_after([1, 2, 4, 5], 2, 3))    # [1, 2, 3, 4, 5]
print(insert_after([1, 2, 3], 99, 0))       # [1, 2, 3, 0]
03

Удалить дубликаты (с сохранением порядка)

#

Напишите функцию `remove_dupes(lst)`, которая удаляет дубликаты из списка, сохраняя порядок первого появления элементов. Пример: `remove_dupes([3, 1, 2, 1, 3, 4])` → `[3, 1, 2, 4]`. Не используйте множества напрямую (они не сохраняют порядок).

def remove_dupes(lst):
    pass


print(remove_dupes([3, 1, 2, 1, 3, 4]))     # [3, 1, 2, 4]
print(remove_dupes([1, 1, 1]))               # [1]
Решение
def remove_dupes(lst):
    seen = set()
    result = []
    for item in lst:
        if item not in seen:
            seen.add(item)
            result.append(item)
    return result


print(remove_dupes([3, 1, 2, 1, 3, 4]))     # [3, 1, 2, 4]
print(remove_dupes([1, 1, 1]))               # [1]
04

Сортировка по ключу

#

Напишите функцию `sort_by_length(words)`, которая возвращает новый список слов, отсортированных по длине (сначала самые короткие). Слова одинаковой длины должны сохранять относительный порядок. Пример: `sort_by_length(["banana", "fig", "apple", "kiwi"])` → `["fig", "kiwi", "apple", "banana"]`.

def sort_by_length(words):
    pass


print(sort_by_length(["banana", "fig", "apple", "kiwi"]))
# ["fig", "kiwi", "apple", "banana"]
Решение
def sort_by_length(words):
    return sorted(words, key=len)


print(sort_by_length(["banana", "fig", "apple", "kiwi"]))
# ["fig", "kiwi", "apple", "banana"]
05

Стек на основе списка

#

Реализуйте простой стек на основе списка. Напишите класс `Stack` с методами: `push(item)`, `pop()` (возвращает и удаляет верхний элемент), `peek()` (возвращает верхний элемент без удаления), `is_empty()`, `size()`. Используйте только методы списка — импорт не нужен.

class Stack:
    def __init__(self):
        self._data = []

    def push(self, item):
        pass

    def pop(self):
        pass

    def peek(self):
        pass

    def is_empty(self):
        pass

    def size(self):
        pass


s = Stack()
s.push(1)
s.push(2)
s.push(3)
print(s.peek())     # 3
print(s.pop())      # 3
print(s.size())     # 2
print(s.is_empty()) # False
Решение
class Stack:
    def __init__(self):
        self._data = []

    def push(self, item):
        self._data.append(item)

    def pop(self):
        return self._data.pop()

    def peek(self):
        return self._data[-1]

    def is_empty(self):
        return len(self._data) == 0

    def size(self):
        return len(self._data)


s = Stack()
s.push(1)
s.push(2)
s.push(3)
print(s.peek())     # 3
print(s.pop())      # 3
print(s.size())     # 2
print(s.is_empty()) # False
06

Безопасная копия

#

Следующий код содержит ошибку. Исправьте его так, чтобы изменение `b` не влияло на `a`: ```python a = [1, 2, 3] b = a b.append(99) print(a) # должен остаться [1, 2, 3] ``` Объясните в комментарии, почему исходный код не работает.

a = [1, 2, 3]
b = a          # ОШИБКА: оба указывают на один список
b.append(99)
print(a)       # должно быть [1, 2, 3], но выводит [1, 2, 3, 99]

# Исправьте код выше чтобы изменение b не влияло на a
Решение
a = [1, 2, 3]
b = a.copy()   # создаёт новый независимый список
b.append(99)
print(a)   # [1, 2, 3]  — без изменений
print(b)   # [1, 2, 3, 99]

# Альтернативы: b = a[:]  или  b = list(a)
07

Распаковка кортежей

#

Напишите функцию `swap(a, b)`, которая возвращает два значения в обратном порядке, используя распаковку кортежа в одну строку. Затем напишите функцию `unpack_first_last(lst)`, которая возвращает кортеж `(first, last)` с помощью звёздочной распаковки. Пример: `unpack_first_last([10, 20, 30, 40])` → `(10, 40)`.

def swap(a, b):
    pass


def unpack_first_last(lst):
    pass


print(swap(1, 2))                    # (2, 1)
print(unpack_first_last([10, 20, 30, 40]))  # (10, 40)
Решение
def swap(a, b):
    return b, a


def unpack_first_last(lst):
    first, *_, last = lst
    return first, last


print(swap(1, 2))                          # (2, 1)
print(unpack_first_last([10, 20, 30, 40])) # (10, 40)
08

Безопасный поиск индекса

#

Напишите функцию `find_index(lst, value)`, которая возвращает индекс `value` в `lst`, или `-1` если не найден. НЕ используйте `.index()` напрямую (он кидает ValueError). Пример: `find_index([10, 20, 30], 20)` → `1`, `find_index([10, 20, 30], 99)` → `-1`.

def find_index(lst, value):
    pass


print(find_index([10, 20, 30], 20))   # 1
print(find_index([10, 20, 30], 99))   # -1
Решение
def find_index(lst, value):
    try:
        return lst.index(value)
    except ValueError:
        return -1


print(find_index([10, 20, 30], 20))   # 1
print(find_index([10, 20, 30], 99))   # -1
09

Самый частый элемент

#

Напишите функцию `most_frequent(lst)`, которая возвращает элемент, встречающийся чаще всего в списке. При равенстве — возвращайте тот, что появился первым. Пример: `most_frequent([1, 2, 2, 3, 1, 2])` → `2`, `most_frequent([5, 5, 3, 3])` → `5`.

def most_frequent(lst):
    pass


print(most_frequent([1, 2, 2, 3, 1, 2]))   # 2
print(most_frequent([5, 5, 3, 3]))          # 5  (первый при равенстве)
Решение
def most_frequent(lst):
    counts = {}
    for item in lst:
        counts[item] = counts.get(item, 0) + 1
    return max(lst, key=lambda x: counts[x])


print(most_frequent([1, 2, 2, 3, 1, 2]))   # 2
print(most_frequent([5, 5, 3, 3]))          # 5  (первый при равенстве)
10

Выровнять на один уровень

#

Напишите функцию `flatten(lst)`, которая принимает список списков и возвращает один плоский список со всеми элементами. Пример: `flatten([[1, 2], [3, 4], [5]])` → `[1, 2, 3, 4, 5]`. Используйте `extend` или генератор списка.

def flatten(lst):
    pass


print(flatten([[1, 2], [3, 4], [5]]))        # [1, 2, 3, 4, 5]
print(flatten([[10, 20], [30], [40, 50]]))   # [10, 20, 30, 40, 50]
Решение
def flatten(lst):
    result = []
    for sub in lst:
        result.extend(sub)
    return result


# Однострочный вариант:
def flatten_v2(lst):
    return [x for sub in lst for x in sub]


print(flatten([[1, 2], [3, 4], [5]]))        # [1, 2, 3, 4, 5]
print(flatten([[10, 20], [30], [40, 50]]))   # [10, 20, 30, 40, 50]