Menu

Списковые включения в Python: синтаксис, фильтрация и dict-comprehension

Списковые включения позволяют построить новый список в одну читаемую строку - отобразить, отфильтровать или и то, и другое - заменяя паттерн цикл + append.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Одна строка - одна идея

Ты уже писал этот паттерн несколько раз: начать с пустого списка, пройти по чему-то, может, отфильтровать и положить в результат.

Списковое включение говорит то же самое в одну строку:

Читается слева направо: «новый список, состоящий из n * 2 для каждого n в numbers». Структура - [expression for item in iterable].

Это не специфичный для Python трюк - его называют comprehension, потому что ты декларативно описываешь, что попадает в новый список, а не расписываешь механику сборки.

Добавляем фильтр

Добавь if после части с циклом - получишь фильтр:

Второе читается: «n * n для каждого n в numbers, но только если n нечётное».

Эквивалентный цикл:

Оба варианта нормальны. Включение короче и, когда прочтёшь несколько, реально быстрее сканируется глазом - намерение прямо в одной строке.

Map и filter одновременно

Можно пропустить значения через функцию и одновременно отфильтровать:

Для каждого слова длиннее 3 символов включаем его версию в верхнем регистре.

Вложенные циклы во включении

Два for-а дают пару в стиле декартова произведения:

Порядок такой же, как если бы ты вложил циклы: первый for - внешний, второй - внутренний. Читается слева направо, как и эквивалентный цикл с отступами.

Два уровня - примерно предел, после которого обычный цикл читается лучше. Дошёл до трёх - переключайся обратно на циклы.

Включения словарей и множеств

Та же идея, другие скобки:

Включения множеств на первый взгляд выглядят так же, как включения словарей, - разница в key: value против одного выражения. Фигурные плюс : - словарь; фигурные без : - множество.

Generator-выражения

Близнец спискового включения, но с круглыми скобками вместо квадратных - и, что критично, он не строит список:

Заметь: генератор мы передали прямо в sum() и any() - без лишних скобок. Generator-выражения - правильный инструмент, когда вызывающей стороне достаточно один раз проитерироваться. Для больших коллекций они экономят память по сравнению с полным списком.

Когда взять обычный цикл

Включения соблазнительны. Технически туда можно напихать много. Не стоит.

Тянись к обычному циклу, когда:

  • Преобразование состоит из нескольких шагов. Если нужны промежуточные переменные - распиши.
  • Есть сложная обработка ошибок или ветвление.
  • Любой читатель вынужден задержаться на строке дважды, чтобы её понять.

Правило, которое я применяю: если могу прочесть включение на одном вдохе и понять, что оно делает, - оно остаётся. Спотыкаюсь - переписываю в цикл.

Некоторые включения выглядят умно, но изматывают:

Результат тот же. Цикл - пять строк вместо одной, но «длиннее» ≠ «хуже».

Несколько паттернов, которые пригодятся

Эти пять паттернов покрывают удивительно большую долю повседневной работы с данными.

Дальше

Ты уже видел основные коллекционные типы и включение, которое их связывает. Следующая глава - функции: упаковка поведения в именованные, переиспользуемые единицы.

Часто задаваемые вопросы

Что такое списковое включение в Python?

Компактный синтаксис для построения нового списка из существующего итерируемого. [x * 2 for x in numbers] создаёт новый список, где каждое число удвоено. Можно и фильтровать: [x for x in numbers if x > 0].

Когда лучше не использовать списковое включение?

Когда страдает читаемость. Если выражение внутри сложное или глубоко вложенное - обычный for-цикл с нормальными именами переменных понятнее. Включения для простых преобразований - отображения и фильтрации. Всё, что сложнее, лучше в полном цикле.

В чём разница между списковым включением и generator-выражением?

Списковое включение строит весь список в памяти. Generator-выражение (тот же синтаксис, но в круглых скобках) выдаёт по одному элементу. Используй генератор, когда результаты передаются чему-то, что итерирует один раз - вроде sum(...) - чтобы не материализовать список, который тут же выбросишь.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ