Гид по технологиям

Генераторы списков в Python — как и когда применять

5 min read Python Обновлено 15 Dec 2025
Генераторы списков в Python — примеры и советы
Генераторы списков в Python — примеры и советы

Текстовый редактор с кодом Python

Генераторы списков (list comprehension) в Python позволяют компактно и быстро преобразовывать и фильтровать последовательности в один выраженный список. Пользуйтесь ими для простых операций преобразования и фильтрации; избегайте глубоко вложенных или побочных выражений — в таких случаях предпочтите явные циклы или функции.

Что такое генераторы списков и как они работают

Генератор списков — это синтаксический способ создать новый список, применив выражение к каждому элементу и, опционально, отфильтровав элементы. Проще: вы описываете правило «как получить новый элемент из старого», и Python сам создаёт список.

Определение в одну строку: генераторы списков состоят из выражения и итератора for, возможна секция if для фильтрации.

Ключевые преимущества:

  • Компактность кода: часто одна строка вместо нескольких строк с .append().
  • Скорость: для многих случаев comprehension работает быстрее эквивалентного Python-цикла, потому что выполняется в C.
  • Ясность: при умеренной сложности читается лучше, чем длинный цикл.

Важно: генераторы списков предназначены для создания коллекций, а не для побочных эффектов (например, записи в файл). Для побочных эффектов используйте обычные циклы или функции.

Синтаксис и базовые примеры

Общий вид:

new_list = [expression for item in iterable]

Пример: получить все кратные трём числа от 3 до 30.

multiples_of_3 = [i * 3 for i in range(1, 11)]
print(multiples_of_3)
# Вывод: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

Эквивалент с явным циклом:

my_list = []
for i in range(1, 11):
    my_list.append(i * 3)
print(my_list)

Фильтрация с помощью if

Добавляем условие, чтобы выбрать только нечётные числа:

odd_numbers = [i for i in range(1, 11) if i % 2 != 0]
print(odd_numbers)
# Вывод: [1, 3, 5, 7, 9]

Тот же код через цикл:

my_list = []
for i in range(1, 11):
    if i % 2 != 0:
        my_list.append(i)
print(my_list)

Вложенные условия и вложенные циклы

Можно добавить несколько условий подряд:

small_odds = [i for i in range(1, 11) if i % 2 != 0 if i < 4]
print(small_odds)
# Вывод: [1, 3]

Вложенные циклы полезны для комбинирования элементов из нескольких итераторов:

pairs = [(i, k) for i in range(1, 3) for k in range(3, 6)]
print(pairs)
# Вывод: [(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5)]

Пример «матричного» вложения (вложенный список):

some_nums = [[i * 2 for i in range(1, 3)] for _ in range(4)]
print(some_nums)
# Вывод: [[2, 4], [2, 4], [2, 4], [2, 4]]

Пример плоской структуры с двумя for в одной строке:

flattened = [i * 2 for i in range(1, 3) for k in range(4)]
print(flattened)
# Вывод: [2, 2, 2, 2, 4, 4, 4, 4]

Работа со строками и подсчёт слов

Пример простого счётчика слов для одного элемента списка:

words = ["This is a python list comprehension tutorial"]
word_counter = [s.count(' ') + 1 for s in words]
print(word_counter)
# Вывод: [7]

Если у вас несколько строк, comprehension вернёт список счётчиков.

Вызов функций внутри comprehension

Вы можете использовать функции в выражении — это удобно для повторного использования логики:

numbers = [4, 7, 8, 15, 17, 10]

def multiplier(n):
    return n * 2

multiple_even = [multiplier(i) for i in numbers if i % 2 == 0]
print(multiple_even)
# Вывод: [8, 16, 20]

multiple_from_odds = [multiplier(i) for i in numbers if i % 2 != 0]
print(multiple_from_odds)
# Вывод: [14, 30, 34]

Генераторы списков помогают распределять результаты по переменным, которые затем удобно превращать в таблицы (DataFrame) или CSV.

Генераторы словарей и множеств

Python поддерживает аналогичный синтаксис для словарей и множеств.

Словарь: ключи — числа, значения — их удвоенные значения:

corresponding = {i: i * 2 for i in range(10) if i % 2 != 0}
print(corresponding)
# Вывод: {1: 2, 3: 6, 5: 10, 7: 14, 9: 18}

Множество (set comprehension) удаляет дубликаты автоматически:

numbers = {i ** 2 for i in range(10) if i % 4 == 0}
print(numbers)
# Вывод: {0, 16, 64}

Пример со сложной генерацией множества и удалением дубликатов:

nums = {i for i in range(20) if i % 2 == 1 for k in range(10) if k % 2 == 1}
print(nums)
# Вывод: {1, 3, 5, 7, 9, 11, 13, 15, 17, 19}

Когда генераторы списков не подходят

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

  • Когда выражение слишком длинное или сложное — это ухудшает читаемость. Разбейте на функции или используйте цикл.
  • Когда требуется короткая память (поток данных большого объёма) — используйте генераторные выражения (круглые скобки) или itertools.
  • Когда важны побочные эффекты (логирование, записи, сетевые вызовы) — лучше явный цикл.
  • Когда нужен контроль над ошибками для каждого элемента — явный цикл даёт более гибкие try/except.

Важно: читаемость обычно важнее компактности. Если comprehension занимает несколько строк или содержит вложенные уровни, подумайте о другом подходе.

Альтернативы и паттерны

  • map + filter: иногда выразительнее, особенно если у вас простые функции.
  • itertools (chain, islice, imap) для ленивых вычислений и работы с большими последовательностями.
  • генераторные выражения: похожи на comprehension, но возвращают итератор и не сохраняют весь результат в памяти.

Пример генераторного выражения:

gen = (i * 3 for i in range(1, 11))
for val in gen:
    print(val)

Правила хорошего использования — чеклист

  • Используйте генераторы списков для простых преобразований и фильтрации.
  • Если код читается дольше 2–3 секунд, сделайте явный цикл или вынесите логику в функцию.
  • Не используйте для побочных эффектов.
  • Для больших наборов данных используйте генераторные выражения.
  • Пишите тесты для сложных comprehension, особенно если в нём вложенные циклы и условия.

Быстродействие и память

В большинстве случаев comprehension быстрее эквивалентного Python-цикла, потому что интерпретатор выполняет меньше операций на стороне Python и использует оптимизации на уровне C. Однако comprehension всегда создает весь список в памяти — это важно для больших данных.

Когда память ограничена, используйте генераторные выражения, itertools или разбивайте данные на чанки.

Паттерны: map/filter и «плоский список»

Преобразование (map): expression for item in iterable Фильтрация (filter): item for item in iterable if condition Плоский список (flattening): [y for x in matrix for y in x]

Пример плоской операции:

matrix = [[1, 2], [3, 4], [5]]
flat = [x for row in matrix for x in row]
print(flat)
# Вывод: [1, 2, 3, 4, 5]

Простая методология принятия решения

  1. Определите, чисто ли это преобразование данных (да/нет).
  2. Если да и результат небольшой — используйте генератор списков.
  3. Если результат большой или ленивость важна — используйте генераторное выражение.
  4. Если логика сложная или есть побочные эффекты — явный цикл или функция.

Decision tree (Mermaid)

flowchart TD
  A[Начало: нужно собрать новый список?] --> B{Логика простая?}
  B -- Да --> C{Память важна?}
  B -- Нет --> G[Использовать явный цикл / функцию]
  C -- Да --> D[Генераторное выражение / itertools]
  C -- Нет --> E[Генератор списка 'list comprehension']
  E --> F[Тесты + читаемость OK]
  D --> F
  G --> F

Частые ошибки и как их избежать

  • Ошибка: использование побочных эффектов внутри comprehension. Решение: вынести в функцию или использовать цикл.
  • Ошибка: слишком сложные вложения. Решение: разбить на несколько шагов, дать им имена.
  • Ошибка: путаница в порядке for-if при нескольких итераторах. Решение: сначала напишите эквивалентный цикл для проверки.

Мини-глоссарий (1 строка каждый)

  • comprehension: выражение для создания коллекции в компактной форме.
  • генераторное выражение: ленивый аналог comprehension, возвращающий итератор.
  • map/filter: функции для преобразования и фильтрации, альтернативы comprehension.

Критерии приёмки

  • Код выполняет требуемое преобразование и покрыт тестами для краевых случаев.
  • Читаемость не уступает явному циклу (рецензия кода пройдена).
  • Память и производительность в пределах требований (если важно).

Заключение

Генераторы списков — мощный инструмент для компактного и быстрого кода в Python. Применяйте их для простых преобразований и фильтрации, но не жертвуйте читаемостью ради краткости. Для больших потоков данных и сложной логики выбирайте генераторные выражения, itertools или явные циклы.

Важно: при сомнении начните с явного цикла, затем рефакторьте в comprehension, если код остаётся понятным.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Добавить Take Ownership в контекстное меню
Windows

Добавить Take Ownership в контекстное меню

Голосовой ввод в Windows 11 — включение и советы
Windows

Голосовой ввод в Windows 11 — включение и советы

Уведомления Google Форм на email — настройка
Google Forms

Уведомления Google Форм на email — настройка

Petey на Apple Watch — ChatGPT на запястье
Приложения

Petey на Apple Watch — ChatGPT на запястье

Искать по содержимому в Windows: добавить типы файлов
Windows

Искать по содержимому в Windows: добавить типы файлов

MicroK8s: быстрый старт и эксплуатация
Kubernetes

MicroK8s: быстрый старт и эксплуатация