Что такое генератор (generator) в Python?

«Что такое генератор (generator) в Python?» — вопрос из категории Python, который задают на 30% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Генератор в Python — это специальный итератор, который позволяет лениво (по требованию) генерировать значения, не храня всю последовательность в памяти одновременно. Это делает их исключительно эффективными для работы с большими или бесконечными потоками данных.

Два основных способа создания:

  1. Функция-генератор (Generator function): Использует ключевое слово yield вместо return. При вызове такая функция возвращает объект-генератор, а её выполнение приостанавливается после каждого yield и возобновляется при следующем вызове next().

    def countdown(n):
        """Генератор, который отсчитывает от n до 1."""
        while n > 0:
            yield n  # Возвращает значение и приостанавливается
            n -= 1
        # По достижении конца функция неявно вызывает StopIteration
    
    # Использование
    for number in countdown(5):
        print(number)  # 5, 4, 3, 2, 1
    
    # Или вручную
    gen = countdown(3)
    print(next(gen))  # 3
    print(next(gen))  # 2
    print(next(gen))  # 1
    # print(next(gen))  # Вызовет StopIteration
  2. Генераторное выражение (Generator expression): Похоже на list comprehension, но использует круглые скобки и ленивые вычисления.

    # List comprehension (сразу создаёт список в памяти)
    squares_list = [x**2 for x in range(1000000)]  # Занимает много памяти
    
    # Generator expression (генерирует значения на лету)
    squares_gen = (x**2 for x in range(1000000))  # Практически не занимает памяти
    print(next(squares_gen))  # 0
    print(next(squares_gen))  # 1

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

  • Экономия памяти: значения вычисляются и возвращаются по одному.
  • Ленивые вычисления: генератор не начинает работу, пока не запрошено первое значение.
  • Работа с бесконечными последовательностями:
    def infinite_counter():
        i = 0
        while True:
            yield i
            i += 1

Под капотом: Генераторы реализуют протокол итератора (методы __iter__() и __next__()), а также имеют методы .send(value), .throw(exception) и .close() для более сложного взаимодействия.

Видео-ответы