Генераторы списков в Python: синтаксис, примеры и когда их избегать

  1. Главная
  2. Блог
  3. Разработка ПО
Разработка ПО

Генераторы списков в Python: синтаксис, примеры и когда их избегать

Изучите генераторы списков (list comprehension) в Python шаг за шагом: создавайте, фильтруйте и преобразуйте списки в одну строку, смотрите измеренное время в сравнении с циклами и узнайте, когда цикл for читается лучше.

7 мин чтения
Генераторы списков в Python: синтаксис, примеры и когда их избегать
Главное
  • Шаблон: [выражение 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, но в первую очередь решает читаемость.

Чем генератор списка отличается от генераторного выражения?

Генератор списка сразу строит весь список в памяти. Генераторное выражение записывается в круглых скобках и выдаёт по одному значению, что экономит память на больших данных.

Можно ли вкладывать генераторы списков друг в друга?

Да, для «выпрямления» или транспонирования матрицы. Ограничьтесь двумя уровнями и переходите на цикл, если код трудно читать.

Продолжайте изучать (статьи на английском)

Работайте со Stack Quora

Нужна помощь с тестированием, WordPress или SEO?

Мы помогаем командам выпускать более качественное ПО и развивать сайты. Расскажите, над чем вы работаете, и мы предложим понятный следующий шаг.

Продолжайте читать

Больше руководств по тестирование, искусственный интеллект и современные разработки

Понравилась эта статья? Выберите тему и сразу приступайте к нашим новейшим руководствам.

Искусственный интеллект

Объяснение галлюцинаций искусственного интеллекта: почему языковые модели все выдумывают и как их уменьшить

Галлюцинации ИИ объяснили: что это такое, почему языковые модели их создают, распространенные типы, как уменьшить их с помощью заземления и подсказо…

Читать статью →
DevOps

Объяснение переменных среды: файлы .env, секреты и правильно выполненная конфигурация

Переменные среды объясняются на примерах Python, которые мы запускали: их чтение и установка, почему каждое значение является строкой, файлы .env, н…

Читать статью →
Разработка ПО

Объяснение ограничения скорости API: алгоритмы, заголовки и обработка ошибок 429

Ограничение скорости API объясняется с помощью проведенного нами моделирования: сегмент токенов, фиксированное окно, скользящее окно, 429 ответов, з…

Читать статью →
Автоматизация тестирования

Издевательство в Python: unittest.mock, патч и ошибки, из-за которых тесты лгут

Издевательство на Python с помощью unittest.mock, протестировано: Mock и return_value, Side_effect, исправление использования имени, спецификация и …

Читать статью →
Тестирование ПО

Объяснение покрытия кода: покрытие линий или ветвей и что на самом деле означает 100%

Покрытие кода объяснено с помощью реального запуска покрытия.py: покрытие строк, ветвей и условий, чтение отчета, почему 100%-ное покрытие все еще м…

Читать статью →
Базы данных и SQL

DELETE, TRUNCATE и DROP в SQL: различия, откат и когда использовать каждый из них

Объяснение DELETE, TRUNCATE и DROP на примере протестированного SQL: что каждый из них удаляет, откат, триггеры, сброс идентификаторов, скорость и ч…

Читать статью →
Базы данных и SQL

Объяснение представлений SQL: создавайте, используйте и избегайте ловушек, с примерами

Представления SQL, объясненные с помощью запросов, которые мы выполняли: создание представления, результаты в реальном времени, скрытие столбцов, пр…

Читать статью →
Разработка ПО

Интерфейс TypeScript и тип: реальные различия, протестированные с помощью компилятора

Интерфейс TypeScript против типа, проверенный реальным компилятором: что могут делать оба, что может делать только один, слияние объявлений, расшире…

Читать статью →
Разработка ПО

Объяснение Python *args и **kwargs: гибкие функции с понятными примерами

Python *args и **kwargs, объясненные с помощью кода, который мы запускали: упаковка и распаковка, порядок параметров, аргументы только по ключевым с…

Читать статью →
Разработка ПО

Лямбда-функции Python: синтаксис, реальное использование и когда их не следует использовать

Лямбда-функции Python, объясненные с помощью кода, который мы запускали: синтаксис, сортировка с помощью ключа, карты и фильтра, замыкания, ловушка …

Читать статью →
Искусственный интеллект

Что такое ИИ-агенты? Как они работают: можно запустить простой цикл агента

Что такое агенты ИИ? Простое руководство по циклу агента, инструментам, памяти и ограничениям, с небольшим циклом Python, который мы запустили, реал…

Читать статью →
DevOps

Мониторинг и наблюдаемость: реальная разница с журналами, метриками и трассировками

Объяснение мониторинга и наблюдаемости: известные и неизвестные сбои, журналы, метрики и трассировки, пошаговое руководство по инцидентам при оформл…

Читать статью →
DevOps

Docker Volumes против Bind Mounts: правильное сохранение данных контейнера

Объяснение томов Docker и монтирования привязки: почему исчезают данные контейнера, именованные тома, монтирование привязки, tmpfs, примеры создания…

Читать статью →
Автоматизация тестирования

TDD против BDD: ключевые различия, одна функция, созданная для обоих способов, и когда использовать каждый

TDD и BDD объясняются с помощью одной функции скидки, созданной в обоих направлениях: красно-зеленый рефакторинг с кодом, который мы запускали, сцен…

Читать статью →
Разработка ПО

Git merge vs rebase: отличия, примеры и когда что использовать

Git merge vs rebase с реальным выводом log, сравнительной таблицей, золотым правилом rebase и безопасным рабочим процессом для команды.

Читать статью →
Разработка ПО

Генераторы списков в Python: синтаксис, примеры и когда их избегать

Генераторы списков в Python: синтаксис, фильтры, if-else, вложенные циклы, измеренное время и случаи, когда обычный цикл for лучше.

Читать статью →
Базы данных и SQL

SQL JOIN: объяснение с примерами (Inner, Left, Right, Full)

Разберите SQL JOIN шаг за шагом на примерах таблиц и запросов: INNER, LEFT, RIGHT, FULL, CROSS и SELF, а также частые ошибки и советы по производите…

Читать статью →