Генераторы списков в Python: синтаксис, примеры и когда их избегать
Изучите генераторы списков (list comprehension) в Python шаг за шагом: создавайте, фильтруйте и преобразуйте списки в одну строку, смотрите измеренное время в сравнении с циклами и узнайте, когда цикл for читается лучше.
- Шаблон:
[выражение for элемент in итерируемое if условие]. - Простой
ifв конце фильтрует, аif-elseв начале выбирает между двумя значениями. - В нашем тесте генератор списка оказался примерно на 37% быстрее цикла с
append. - Для огромных данных переходите на генераторное выражение, а для логики из нескольких понятных шагов — на обычный цикл.
Генератор списка в Python создаёт новый список из любого итерируемого объекта в одной читаемой строке. Вместо того чтобы создавать пустой список, обходить данные и вызывать append, вы описываете нужный результат.
Это руководство проходит путь от базового шаблона до фильтров, вложенных циклов и замеров, которые мы сделали сами. Если вы новичок в Python, начните с нашего учебника по Python для начинающих (на английском) и держите окружение в порядке с помощью руководства по виртуальным окружениям (на английском).
Синтаксис генератора списка в Python
Читайте слева направо: выражение показывает, как выглядит каждый новый элемент, а часть for — откуда берутся элементы.
squares = [x * x for x in range(6)]
print(squares) # [0, 1, 4, 9, 16, 25]
names = [" Hi ", " QA "]
clean = [n.strip().lower() for n in names]
print(clean) # ['hi', 'qa']
Тот же результат с циклом потребует на три строки больше. В этом и смысл, пока строка остаётся простой для чтения.
Фильтрация элементов по условию
Добавьте if после цикла, чтобы оставить только элементы, прошедшие условие.
evens = [x for x in range(10) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8]
Генератор списка в Python с if-else
Если нужно значение для каждого элемента, ставьте if-else перед for. Именно здесь чаще всего ошибаются новички, потому что else в конце — синтаксическая ошибка.
labels = ["even" if x % 2 == 0 else "odd" for x in range(4)]
print(labels) # ['even', 'odd', 'even', 'odd']
Простое правило: if в конце убирает элементы, if-else в начале изменяет их. При if-else длина списка не меняется.
Вложенные циклы и «выпрямление» списков
Несколько частей for читаются в том же порядке, что и вложенные циклы. С их помощью можно «выпрямить» список списков или составить пары.
matrix = [[1, 2, 3], [4, 5, 6]]
flat = [n for row in matrix for n in row]
print(flat) # [1, 2, 3, 4, 5, 6]
pairs = [(x, y) for x in range(1, 3) for y in "ab"]
print(pairs) # [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
Чтобы транспонировать матрицу, вложите один генератор в другой: [[r[i] for r in matrix] for i in range(3)] даёт [[1, 4], [2, 5], [3, 6]]. Два уровня — практический предел, после которого читаемость падает.
Формы для словаря, множества и генератора
Смените скобки, и та же идея создаёт другие типы.
lengths = {w: len(w) for w in ["pip", "venv", "uv"]} # {'pip': 3, 'venv': 4, 'uv': 2}
unique = {len(w) for w in ["pip", "venv", "uv", "git"]} # {2, 3, 4}
total = sum(x * x for x in range(1_000_000)) # generator, no list
Сами типы сравните в нашем руководстве по спискам, кортежам, множествам и словарям (на английском).
Скорость и память: что мы измерили
Мы замерили каждый вариант на Python 3.13.6 со 100 000 целых чисел, взяв лучший результат из пяти запусков. Ваши цифры будут другими, но порядок сохранится.
| Задача | Время |
|---|---|
Цикл с append (удвоить каждый элемент) | 5,18 мс |
| Генератор списка (удвоить каждый элемент) | 3,25 мс |
list(map(lambda ...)) | 6,50 мс |
| Отбор чётных циклом | 3,62 мс |
| Отбор чётных генератором списка | 3,43 мс |
Генератор списка заметно быстрее цикла с append, но разрыв сокращается, когда основное время уходит на проверку условия. По памяти список из миллиона удвоенных чисел занял около 8,4 МБ, а соответствующий объект-генератор — 200 байт, поскольку он выдаёт значения по одному.
Когда не стоит использовать генератор списка
- Вам нужны только побочные эффекты, например печать или сохранение. Используйте обычный цикл: генератор списка создаст ненужный список.
- В логике несколько шагов. Если нужна вторая переменная или
try, напишите цикл или небольшую функцию. - Данных очень много. Используйте генераторное выражение, чтобы Python не хранил весь список в памяти.
- Нужно больше двух частей
for. Разбейте на именованные шаги ради следующего читателя.
Итоги
Используйте генератор списка в Python, когда короткая строка точно выражает вашу мысль, и цикл — когда нет. Начните с базового шаблона, добавьте фильтр, а затем тренируйте форму с if-else, пока порядок не станет естественным.
Часто задаваемые вопросы
Что такое list comprehension в Python?
Это компактный способ создать список, применив выражение к каждому элементу итерируемого объекта, с необязательным условием для фильтрации.
Как использовать if-else в генераторе списка?
Поставьте условное выражение перед частью for, например ["even" if x % 2 == 0 else "odd" for x in nums]. Для простого фильтра достаточно одного if после цикла.
Генератор списка быстрее цикла for?
Обычно да. В нашем тесте на 100 000 элементов он оказался примерно на 37% быстрее цикла с append, но в первую очередь решает читаемость.
Чем генератор списка отличается от генераторного выражения?
Генератор списка сразу строит весь список в памяти. Генераторное выражение записывается в круглых скобках и выдаёт по одному значению, что экономит память на больших данных.
Можно ли вкладывать генераторы списков друг в друга?
Да, для «выпрямления» или транспонирования матрицы. Ограничьтесь двумя уровнями и переходите на цикл, если код трудно читать.
Продолжайте изучать (статьи на английском)
Нужна помощь с тестированием, WordPress или SEO?
Мы помогаем командам выпускать более качественное ПО и развивать сайты. Расскажите, над чем вы работаете, и мы предложим понятный следующий шаг.
Больше руководств по тестирование, искусственный интеллект и современные разработки
Понравилась эта статья? Выберите тему и сразу приступайте к нашим новейшим руководствам.
Объяснение галлюцинаций искусственного интеллекта: почему языковые модели все выдумывают и как их уменьшить
Галлюцинации ИИ объяснили: что это такое, почему языковые модели их создают, распространенные типы, как уменьшить их с помощью заземления и подсказо…
Читать статью →DevOpsОбъяснение переменных среды: файлы .env, секреты и правильно выполненная конфигурация
Переменные среды объясняются на примерах Python, которые мы запускали: их чтение и установка, почему каждое значение является строкой, файлы .env, н…
Читать статью →Разработка ПООбъяснение ограничения скорости API: алгоритмы, заголовки и обработка ошибок 429
Ограничение скорости API объясняется с помощью проведенного нами моделирования: сегмент токенов, фиксированное окно, скользящее окно, 429 ответов, з…
Читать статью →Автоматизация тестированияИздевательство в Python: unittest.mock, патч и ошибки, из-за которых тесты лгут
Издевательство на Python с помощью unittest.mock, протестировано: Mock и return_value, Side_effect, исправление использования имени, спецификация и …
Читать статью →Тестирование ПООбъяснение покрытия кода: покрытие линий или ветвей и что на самом деле означает 100%
Покрытие кода объяснено с помощью реального запуска покрытия.py: покрытие строк, ветвей и условий, чтение отчета, почему 100%-ное покрытие все еще м…
Читать статью →Базы данных и SQLDELETE, TRUNCATE и DROP в SQL: различия, откат и когда использовать каждый из них
Объяснение DELETE, TRUNCATE и DROP на примере протестированного SQL: что каждый из них удаляет, откат, триггеры, сброс идентификаторов, скорость и ч…
Читать статью →Базы данных и SQLОбъяснение представлений SQL: создавайте, используйте и избегайте ловушек, с примерами
Представления SQL, объясненные с помощью запросов, которые мы выполняли: создание представления, результаты в реальном времени, скрытие столбцов, пр…
Читать статью →Разработка ПОИнтерфейс TypeScript и тип: реальные различия, протестированные с помощью компилятора
Интерфейс TypeScript против типа, проверенный реальным компилятором: что могут делать оба, что может делать только один, слияние объявлений, расшире…
Читать статью →Разработка ПООбъяснение Python *args и **kwargs: гибкие функции с понятными примерами
Python *args и **kwargs, объясненные с помощью кода, который мы запускали: упаковка и распаковка, порядок параметров, аргументы только по ключевым с…
Читать статью →Разработка ПОЛямбда-функции Python: синтаксис, реальное использование и когда их не следует использовать
Лямбда-функции Python, объясненные с помощью кода, который мы запускали: синтаксис, сортировка с помощью ключа, карты и фильтра, замыкания, ловушка …
Читать статью →Искусственный интеллектЧто такое ИИ-агенты? Как они работают: можно запустить простой цикл агента
Что такое агенты ИИ? Простое руководство по циклу агента, инструментам, памяти и ограничениям, с небольшим циклом Python, который мы запустили, реал…
Читать статью →DevOpsМониторинг и наблюдаемость: реальная разница с журналами, метриками и трассировками
Объяснение мониторинга и наблюдаемости: известные и неизвестные сбои, журналы, метрики и трассировки, пошаговое руководство по инцидентам при оформл…
Читать статью →DevOpsDocker Volumes против Bind Mounts: правильное сохранение данных контейнера
Объяснение томов Docker и монтирования привязки: почему исчезают данные контейнера, именованные тома, монтирование привязки, tmpfs, примеры создания…
Читать статью →Автоматизация тестированияTDD против BDD: ключевые различия, одна функция, созданная для обоих способов, и когда использовать каждый
TDD и BDD объясняются с помощью одной функции скидки, созданной в обоих направлениях: красно-зеленый рефакторинг с кодом, который мы запускали, сцен…
Читать статью →Разработка ПОGit merge vs rebase: отличия, примеры и когда что использовать
Git merge vs rebase с реальным выводом log, сравнительной таблицей, золотым правилом rebase и безопасным рабочим процессом для команды.
Читать статью →Разработка ПОГенераторы списков в Python: синтаксис, примеры и когда их избегать
Генераторы списков в Python: синтаксис, фильтры, if-else, вложенные циклы, измеренное время и случаи, когда обычный цикл for лучше.
Читать статью →Базы данных и SQLSQL JOIN: объяснение с примерами (Inner, Left, Right, Full)
Разберите SQL JOIN шаг за шагом на примерах таблиц и запросов: INNER, LEFT, RIGHT, FULL, CROSS и SELF, а также частые ошибки и советы по производите…
Читать статью →