Перейти к содержимому
Главная страница

Списки в Python: что это такое и как с ними работать

Изображение с заголовком «Lists in Python»

Списки (list) в Python: полный гид по созданию, изменениям и эффективной работе

Список в Python — универсальная коллекция общего назначения. Он поддерживает произвольные типы, изменяется «на месте», легко комбинируется с циклами, генераторами и функциями стандартной библиотеки. Ниже — системный разбор: от базовых операций до нюансов сортировки, копирования и производительности.

Ключевая идея

Список — упорядоченная и изменяемая последовательность. Это означает:

  • Порядок элементов сохраняется.
  • Можно добавлять, удалять и заменять элементы без пересоздания объекта.
  • Поддерживаются смешанные типы и вложенные структуры.
Базовые примеры и мутабельность
empty = []
mix = [1, "a", 3.14, True]
grid = [[1, 2], [3, 4]]        # вложенные списки

mix[0] = 42                    # изменение «на месте»

Важно: переменные хранят ссылку на объект. Присваивание создаёт вторую ссылку, а не копию.

Ссылочная семантика
a = [1, 2, 3]
b = a
b.append(99)
print(a)  # [1, 2, 3, 99]

Создание списков

  • Литерал: []
  • Конструктор: list(iterable)
  • Преобразование из других коллекций: tuple, set, range
  • Генератор списка (list comprehension)
Способы создать список
L1 = [1, 2, 3]
L2 = list("abc")            # ['a', 'b', 'c']
L3 = list(range(5))         # [0, 1, 2, 3, 4]
tpl = (10, 20)
L4 = list(tpl)              # [10, 20]
squares = [x * x for x in range(6)]
Правильная и неправильная матрица
bad = [[0] * 3] * 2
bad[0][0] = 9
print(bad)  # [[9, 0, 0], [9, 0, 0]]

good = [[0] * 3 for _ in range(2)]  # независимые строки

Индексация и срезы

Индексация с нуля. Отрицательные индексы отсчитываются с конца. Срезы создают новый список; присваивание срезу изменяет исходный.

Доступ, срезы и присваивание срезу
L = ["a", "b", "c", "d", "e"]
L[0], L[-1]               # 'a', 'e'
L[1:4]                    # ['b', 'c', 'd']
L[::2]                    # ['a', 'c', 'e']
copy1 = L[:]              # поверхностная копия
L[1:3] = ["B", "C"]       # ['a', 'B', 'C', 'd', 'e']

Операции со списками

  • len(L) — размер;
  • in/not in — проверка наличия;
  • + — конкатенация; * — повторение;
  • лексикографическое сравнение по элементам.
Операции и сравнения
nums = [1, 2, 3]
len(nums)              # 3
2 in nums              # True
nums + [4, 5]          # [1, 2, 3, 4, 5]
["a"] * 3              # ['a', 'a', 'a']

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

Добавление

append(x) — один элемент в конец; extend(iterable) — добавить элементы итерируемого; insert(i, x) — вставка по индексу.

append, extend, insert
L = [1, 2]
L.append(3)                # [1, 2, 3]
L.extend([4, 5])           # [1, 2, 3, 4, 5]
L.insert(1, 100)           # [1, 100, 2, 3, 4, 5]

# типичная путаница:

L = [1, 2]; L.append([3, 4])  # [1, 2, [3, 4]] (один элемент-список)

Удаление и извлечение

remove(x) — удаляет первое вхождение; pop(i=-1) — возвращает и удаляет элемент по индексу; clear() — очищает список.

remove, pop, clear
L = ["a", "b", "b", "c"]
L.remove("b")         # ["a", "b", "c"]
last = L.pop()        # "c", теперь ["a", "b"]
first = L.pop(0)      # "a", теперь ["b"]
L.clear()             # []

Поиск и подсчёт

index(x[, start[, end]]) — индекс первого вхождения; count(x) — количество элементов, равных x.

index и count
L = [10, 20, 10, 30]
L.index(10)        # 0
L.index(10, 1)     # 2
L.count(10)        # 2

Порядок элементов

sort(key=None, reverse=False) — сортирует «на месте»; reverse() — разворачивает список; функция sorted() возвращает новый список.

Сортировка и разворот
L = ["Bob", "alice", "Carol"]
L.sort()                 # ['Bob', 'Carol', 'alice'] (Unicode-порядок)
L.sort(key=str.lower)    # ['alice', 'Bob', 'Carol'] (без регистра)
L.reverse()              # ['Carol', 'Bob', 'alice']

nums = [3, 1, 2]
sorted(nums)             # [1, 2, 3]; исходник не меняется

Копирование

Поверхностная копия: L.copy() или L[:]. Для вложенных структур — copy.deepcopy.

Поверхностная vs глубокая копия
import copy
L = [[1], [2]]
shallow = L.copy()
deep = copy.deepcopy(L)
L[0].append(99)
print(shallow)   # [[1, 99], [2]]
print(deep)      # [[1], [2]]

Итерация и распаковка

Для доступа к индексам используйте enumerate, для параллельного обхода нескольких коллекций — zip. Удобна «звёздная распаковка».

enumerate, zip, звёздная распаковка
colors = ["red", "green", "blue"]
for i, c in enumerate(colors, start=1):
    print(i, c)

xs = [1, 2, 3]; ys = [4, 5, 6]
for x, y in zip(xs, ys):
print(x, y)

head, *middle, tail = [10, 20, 30, 40]
print(head, middle, tail)  # 10 [20, 30] 40

Генераторы списков

Лаконичный синтаксис для построения коллекций с преобразованием и фильтрацией. Когда логика становится громоздкой, лучше перейти к обычному циклу.

Шаблоны использования
evens = [x for x in range(10) if x % 2 == 0]
pairs = [(x, y) for x in range(3) for y in range(2)]
labels = ["even" if x % 2 == 0 else "odd" for x in range(5)]

# эквивалент через цикл для сложных сценариев

res = []
for x in range(10):
if x % 2 == 0:
res.append(x)

Вложенные списки (таблицы/матрицы)

«Список списков» — удобная модель двумерных данных. Следите за независимостью строк и осторожно копируйте.

Матрица и доступ по двум индексам
M = [[1, 2, 3], [4, 5, 6]]
M[1][2]  # 6

rows, cols = 2, 3
M = [[0] * cols for _ in range(rows)]

Стандартные функции, которые «любят» списки

  • sum, min, max — агрегирование;
  • any, all — логические проверки с коротким замыканием;
  • sorted — сортировка без изменения исходника;
  • map, filter — преобразование/фильтрация (часто читаемее через генераторы).
Агрегирование и сортировка по ключу
nums = [3, 5, 1, 4]
sum(nums), min(nums), max(nums)          # 13, 1, 5
any(n % 2 == 0 for n in nums)            # есть ли чётные
all(n > 0 for n in nums)                 # все ли положительные
data = [{"name": "bob", "age": 30}, {"name": "ann", "age": 20}]
sorted(data, key=lambda d: d["age"])

Производительность: что важно знать

  • append — амортизированно O(1).
  • Вставки/удаления в середине — O(n).
  • Частые операции «в начале» удобнее переносить на collections.deque.
  • Не конкатенируйте списки в цикле через +; собирайте элементы и применяйте extend один раз.

Полезные паттерны

  • Стек: append / pop().
  • Очередь: используйте collections.deque для popleft.
  • Удаление по условию: создавайте новый список, а не меняйте текущий в процессе обхода.
  • Сохранить порядок и удалить дубликаты — через «множество виденных».
Удаление дубликатов с сохранением порядка
seen, out = set(), []
for x in [1, 2, 2, 3, 1, 4]:
    if x not in seen:
        seen.add(x); out.append(x)
print(out)  # [1, 2, 3, 4]

Антипаттерны и частые ошибки

  • Путаница append/extend.
  • Ссылки вместо копий (нужны copy, срез или deepcopy для вложенных структур).
  • [[0]*N]*M для матриц — общие ссылки на строки.
  • Изменение списка во время итерации по нему.
  • Сравнение значений через is вместо ==.
Безопасная фильтрация без «прыгающих» индексов
L = [1, 2, 3, 4, 5]
L = [x for x in L if x % 2 == 0]

Практикум

4 упражнения
# 1) чётные квадраты
nums = [1, 2, 3, 4, 5, 6]
print([n * n for n in nums if n % 2 == 0])  # [4, 16, 36]

# 2) разворачивание вложенного списка

nested = [[1, 2], [3, 4, 5]]
flat = [x for sub in nested for x in sub]
print(flat)

# 3) частоты элементов

data = ["a", "b", "a", "c", "b", "a"]
freq = {}
for x in data:
freq[x] = freq.get(x, 0) + 1
print(freq)

# 4) сортировка по второму элементу кортежа (по убыванию)

items = [("a", 3), ("b", 1), ("c", 2)]
print(sorted(items, key=lambda t: t[1], reverse=True))

FAQ

Чем отличаются append и extend?

append(x) добавляет один объект как единую сущность; extend(iterable) добавляет элементы итерируемого по одному.

append vs extend
L = [1, 2]; L.append([3, 4])  # [1, 2, [3, 4]]
L = [1, 2]; L.extend([3, 4])  # [1, 2, 3, 4]

Когда использовать sort, а когда sorted?

list.sort() меняет список «на месте» и возвращает None; sorted(iterable) создаёт новый список, исходник сохраняется.

Почему умножение списка с вложенными данными даёт неожиданный результат?

Повторяются ссылки на один и тот же вложенный объект. Для независимых строк используйте генератор списков.

Как копировать списки корректно?

Поверхностно: L.copy() или L[:]. Глубоко: copy.deepcopy для вложенных структур.

Как развернуть список?

reverse() меняет порядок «на месте», срез L[::-1] возвращает новую перевёрнутую копию.

Итоги

Списки — фундаментальный инструмент Python. Освойте создание и срезы, грамотно используйте методы добавления/удаления, помните о стабильной сортировке и различии поверхностных и глубоких копий. Учитывайте стоимость операций и выбирайте подходящую структуру данных под задачу. Регулярная практика быстро превращает эти приёмы в автоматизм. 💪

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

Достигнут лимит времени. Пожалуйста, введите CAPTCHA снова.

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии