Skip to content

Generator

Определение#

Генератор — это специальный тип функции, которая возвращает итератор. Она позволяет возвращать значения по одному, не сохраняя всю последовательность в памяти целиком.

Зачем нужны#

Generators — идеальный выбор для работы с огромными наборами данных или бесконечными потоками. Они реализуют принцип lazy evaluation (ленивых вычислений): следующее значение вычисляется только тогда, когда оно действительно потребовалось. Это экономит мегабайты оперативной памяти, так как в ней всегда находится только один текущий элемент.

Как работает#

Вместо ключевого слова return в генераторах используется yield. Когда выполнение доходит до yield, функция возвращает значение и «замораживается», сохраняя все свои локальные переменные и текущую позицию. При следующем вызове (через функцию next() или в цикле for) она продолжает работу ровно с того места, где остановилась.

Характеристика Обычная функция Генератор
Выход из функции return (завершает работу) yield (пауза и сохранение состояния)
Результат Одно значение или список Итератор (объект-генератор)
Память Хранит всё сразу в RAM Вычисляет элементы на ходу

Основные методы#

Метод Что делает Особенности
__next__ Возвращает следующее значение. Вызывается автоматически при использовании функции next(gen) или в цикле for.
__send__ Отправляет значение в генератор. value становится результатом текущего выражения yield внутри генератора.
__throw__ Бросает исключение в месте паузы. Позволяет генератору обработать ошибку или завершиться через try...except.
__close__ Останавливает генератор. Выбрасывает GeneratorExit внутри генератора, чтобы он мог корректно освободить ресурсы.

Примеры#

    # 1. Функция-генератор
    def count_up_to(max_val):
        count = 1
        while count <= max_val:
            yield count  # Здесь функция ставится на паузу
            count += 1

    counter = count_up_to(3)
    print(next(counter))  # 1
    print(next(counter))  # 2

    # 2. Генераторное выражение (Generator Expression)
    # Работает как list comprehension, но в круглых скобках
    squares_gen = (x**2 for x in range(1000000))

    # В памяти только "инструкция", а не миллион чисел
    print(next(squares_gen))  # 0

Ключевые мысли#

  • Генераторы позволяют обрабатывать данные, которые не влезают в оперативную память.
  • Состояние функции (локальные переменные) автоматически сохраняется между вызовами yield.
  • После того как все значения возвращены, генератор выбрасывает исключение StopIteration, что позволяет циклам for корректно завершаться.