Почти любая программа на бэкенде — это перекладывание данных из одной коллекции в другую: собрать список заказов, сгруппировать их по клиенту, отфильтровать оплаченные. Python даёт четыре базовые структуры данных, и большая часть повседневного кода держится именно на них. Разберём, когда что брать и какими приёмами их удобно обрабатывать.
Четыре базовые структуры: когда что
У Python есть четыре встроенные коллекции, и выбор между ними — это первое решение, которое вы принимаете, держа данные в памяти.
list — упорядоченный изменяемый список. Это рабочая лошадка: элементы идут по порядку, их можно добавлять, удалять и менять на месте. Берите list, когда порядок важен и набор будет меняться.
orders = ["a-1", "a-2", "a-3"]
orders.append("a-4") # добавили в конец
orders[0] = "a-0" # поменяли элемент на месте
tuple — упорядоченный, но неизменяемый набор. После создания его нельзя поменять. Кортеж берут для фиксированной записи из нескольких полей (например, пара «широта, долгота») и там, где важно, что данные не «поедут».
point = (55.75, 37.62) # координаты, менять не нужно
# point[0] = 0 # ошибка: tuple неизменяем
Короткая формула: list — для однородной коллекции, которая растёт; tuple — для фиксированной записи из разнородных полей.
dict — словарь, набор пар «ключ → значение». Главный инструмент, когда нужно находить данные по ключу, а не перебирать всё подряд. Поиск по ключу быстрый и не зависит от размера словаря.
prices = {"apple": 50, "bread": 30}
prices["milk"] = 70 # добавили пару
print(prices["apple"]) # быстрый доступ по ключу → 50
print(prices.get("eggs", 0)) # get с значением по умолчанию, без ошибки
set — множество уникальных элементов без порядка. Берут, чтобы убрать дубликаты или быстро проверить «есть ли элемент в наборе».
seen = {"a", "b", "a"} # дубликат отбросится → {"a", "b"}
print("a" in seen) # быстрая проверка вхождения → True
unique = set([1, 2, 2, 3]) # убрать дубликаты из списка → {1, 2, 3}
Ключи dict и элементы set должны быть хешируемыми — то есть неизменяемыми. Строка, число, tuple подойдут как ключ; list — нет. Если нужно неизменяемое множество (например, как ключ словаря), есть frozenset.
Срезы (slicing)
Срез — это способ взять кусок последовательности (list, tuple, строки) по синтаксису [start:stop:step]. Граница start включается, stop — нет.
nums = [0, 1, 2, 3, 4, 5]
print(nums[1:4]) # с 1-го по 3-й → [1, 2, 3]
print(nums[:3]) # первые три → [0, 1, 2]
print(nums[3:]) # с 3-го до конца → [3, 4, 5]
print(nums[::2]) # каждый второй → [0, 2, 4]
print(nums[::-1]) # развернуть → [5, 4, 3, 2, 1, 0]
Отрицательные индексы считают с конца: nums[-1] — последний элемент, nums[-2:] — два последних. Срез списка возвращает новый список, исходный не меняется.
Comprehensions
Comprehension — это компактный способ построить коллекцию из другой одной строкой, вместо цикла с append. Это одна из самых узнаваемых черт Python.
Списковое (list comprehension) — собрать новый список:
nums = [1, 2, 3, 4, 5]
squares = [n * n for n in nums] # [1, 4, 9, 16, 25]
evens = [n for n in nums if n % 2 == 0] # с фильтром → [2, 4]
Читается слева направо как фраза: «возьми n * n для каждого n из nums». Условие if в конце оставляет только подходящие элементы.
Словарное (dict comprehension) — построить словарь:
prices = {"apple": 50, "bread": 30}
# поднять цены на 10%
updated = {name: price * 1.1 for name, price in prices.items()}
Множественное (set comprehension) — собрать множество уникальных значений:
words = ["aa", "bb", "aa", "ccc"]
lengths = {len(w) for w in words} # уникальные длины → {2, 3}
Comprehension хорош для простых преобразований. Если внутри появляется сложная логика в несколько действий — лучше вернуться к обычному циклу, так читается понятнее.
Распаковка (unpacking)
Распаковка позволяет «разложить» коллекцию по нескольким переменным за одно присваивание.
point = (55.75, 37.62)
lat, lon = point # lat = 55.75, lon = 37.62
Звёздочка * собирает «остаток» в список — удобно, когда часть элементов нужна по отдельности, а часть скопом:
first, *rest = [1, 2, 3, 4] # first = 1, rest = [2, 3, 4]
*head, last = [1, 2, 3, 4] # head = [1, 2, 3], last = 4
Распаковка словаря через ** пригодится, чтобы слить два словаря или передать набор именованных аргументов:
defaults = {"host": "localhost", "port": 5432}
override = {"port": 6432}
config = {**defaults, **override} # {"host": "localhost", "port": 6432}
Распаковка же стоит за обменом значениями без временной переменной:
a, b = 1, 2
a, b = b, a # теперь a = 2, b = 1
Сортировка и ключи
Функция sorted возвращает новый отсортированный список, а метод list.sort() сортирует список на месте. Для случайного набора берите sorted — он не портит исходные данные.
nums = [3, 1, 2]
print(sorted(nums)) # [1, 2, 3], nums не изменился
print(sorted(nums, reverse=True)) # по убыванию → [3, 2, 1]
Самое полезное — параметр key: функция, которая для каждого элемента возвращает значение, по которому сравнивать. Так сортируют объекты по нужному полю.
orders = [
{"id": "a", "total": 300},
{"id": "b", "total": 100},
{"id": "c", "total": 200},
]
by_total = sorted(orders, key=lambda o: o["total"])
# отсортировано по сумме: b (100), c (200), a (300)
Если ключ возвращает tuple, сортировка идёт по нескольким полям по очереди — сначала по первому, при равенстве по второму:
people = [("Ann", 30), ("Bob", 25), ("Ann", 25)]
# сначала по имени, потом по возрасту
print(sorted(people, key=lambda p: (p[0], p[1])))
# [("Ann", 25), ("Ann", 30), ("Bob", 25)]
Базовые приёмы работы с коллекциями
Несколько идиом, которые встречаются постоянно.
Перебор с индексом — enumerate вместо ручного счётчика:
for i, name in enumerate(["a", "b", "c"]):
print(i, name) # 0 a / 1 b / 2 c
Параллельный перебор двух списков — zip склеивает их по позициям:
names = ["apple", "bread"]
prices = [50, 30]
catalog = dict(zip(names, prices)) # {"apple": 50, "bread": 30}
Проверка вхождения — оператор in. Для set и dict это быстро независимо от размера, для list — перебором, поэтому для частых проверок «есть ли элемент» выбирайте set.
Группировка/подсчёт — словарь как накопитель:
words = ["a", "b", "a", "a", "b"]
counts = {}
for w in words:
counts[w] = counts.get(w, 0) + 1 # {"a": 3, "b": 2}
Коротко
- list — упорядоченный изменяемый список; tuple — неизменяемая фиксированная запись; dict — быстрый поиск по ключу; set — уникальные элементы и быстрая проверка вхождения.
- Ключи dict и элементы set должны быть хешируемыми (неизменяемыми): строка, число, tuple — да; list — нет.
- Срезы
[start:stop:step]берут кусок последовательности;stopне включается, отрицательный шаг разворачивает. - Comprehensions строят list/dict/set одной строкой; для сложной логики возвращайтесь к обычному циклу.
- Распаковка раскладывает коллекции по переменным;
*собирает остаток,**сливает словари. sortedвозвращает новый список; параметрkeyзадаёт поле сортировки, tuple в ключе — сортировку по нескольким полям.enumerate,zip,inи словарь-накопитель — повседневные идиомы обработки коллекций.
Что почитать дальше
- Синтаксис и типы Python — базовые типы, на которых строятся коллекции.
- Функции и модули — lambda, аргументы и как раскладывать код по файлам.
- Итераторы и генераторы — как перебор коллекций работает изнутри и как обрабатывать данные лениво.