1. Comprehensions: списки, словари, множества и генераторы
Comprehensions: списки, словари, множества и генераторы
Вы уже пишете рабочий Python-код (условия, циклы, функции, списки, словари). Дальше часто встречается стиль, который делает код короче, быстрее и выразительнее: comprehensions и generator expressions.
Официальная документация:
Что такое comprehension и зачем он нужен
Comprehension — это компактная запись создания коллекции (списка, множества, словаря) на основе другой коллекции или любого итерируемого объекта.
Идея:
for)if)Comprehension почти всегда можно переписать в обычный for-цикл. В рабочем коде это полезно потому что:
append, и т.д.)Базовый list comprehension
Общий шаблон:
Где:
итерируемое — то, по чему можно пройти в цикле for (например, список, строка, range, файл)переменная — текущий элементвыражение — что положить в результатif условие — фильтр: пропускаем только элементы, для которых условие истинноПример: получить квадраты чётных чисел.
Обычный цикл:
То же самое comprehension:
Важно: if в конце — это фильтр
Этот if убирает элементы, а не подставляет альтернативное значение.
Условное выражение внутри comprehension
Если вам нужно оставить все элементы, но одни преобразовать так, а другие иначе — используйте условное выражение (тернарное): A if cond else B.
Сравните:
[... for x in xs if cond] — фильтруем, уменьшаем количество элементов[(... if cond else ...) for x in xs] — преобразуем, количество элементов сохраняетсяДва for (вложенные циклы)
Comprehension поддерживает несколько for — это соответствует вложенным циклам слева направо.
Эквивалент обычному коду:
Фильтр можно добавлять на любом уровне:
Рекомендация по читаемости
Comprehension хорош, когда:
Если вы начинаете “программировать внутри comprehension” — чаще лучше вернуться к обычному for.
Dict comprehension (словари)
Шаблон:
Пример: привести строки к целым числам и построить словарь имя -> длина.
Пример: отфильтровать словарь.
Здесь используется prices.items(), который отдаёт пары (ключ, значение).
Частый кейс: инвертировать словарь
Ограничение: если значения повторяются, при инвертировании останется только последнее.
Set comprehension (множества)
Множество — коллекция уникальных элементов.
Шаблон:
Пример: получить уникальные домены из email-адресов.
Здесь set comprehension удобен тем, что дедупликация происходит автоматически.
Generator expression (генераторное выражение)
List/set/dict comprehension сразу создают результат целиком в памяти.
Generator expression создаёт генератор — объект, который выдаёт элементы по одному, “по требованию”. Это называется ленивые вычисления.
Синтаксис похож, но используются круглые скобки:
Пример: посчитать сумму квадратов без создания промежуточного списка.
Если бы вы написали sum([x * x for x in range(1_000_000)]), то сначала создали бы огромный список, а потом посчитали сумму.
!Схема разницы: “сразу в память” против “по одному элементу”.
Где генераторы особенно полезны
Пример: взять числа из файла, отфильтровать и посчитать среднее.
Здесь nums и positives не хранят все числа в памяти.
Важное свойство генератора: он одноразовый
Генератор “расходуется” при итерации.
Если вам нужно многократно проходить по данным — используйте список или создавайте генератор заново.
Технические детали, которые важно знать в рабочем коде
Область видимости переменной в comprehension
В Python 3 переменная цикла внутри list/set/dict comprehension не “протекает” наружу.
Это полезно: comprehension не портит переменные снаружи.
Скобки вокруг generator expression
Если generator expression — единственный аргумент функции, внешние скобки можно опустить:
Но если аргументов несколько — скобки нужны:
Побочные эффекты и comprehension
Comprehension — инструмент для создания коллекций. Не стоит использовать его для “выполнить действие много раз”. Например, так делать не надо:
Правильно — обычный цикл:
Как понимать comprehensions в чужом коде
Практический алгоритм чтения:
[...] — список
- {...} с key: value — словарь
- {...} без : — множество
- (...) — генератор
for x in ...
if ...Итоги и связь с курсом
Вы научились:
if от условного выражения A if cond else BВ следующих статьях курса мы расширим “рабочий синтаксис”:
и *) в выражениях и вызовах функций:=, объединение словарей | и обновление |=