Перейти к основному содержимому

Генератор — это функция, которая может приостановиться и позже продолжить работу.

При вызове функции-генератора вы получаете объект генератора, и этот объект является итератором.

Ни одна строка его кода ещё не выполнена. Выполнение начинается, только когда вы перебираете генератор.

Пример

Простая функция-генератор:

Prompt
Напишите программу на Python, которая определяет функцию-генератор my_generator(), выдающую 1, 2 и 3. С помощью цикла for переберите генератор и выведите каждое значение.
Вывод: полная программа на Python

Ключевое слово yield

Функцию превращает в генератор ключевое слово yield.

Дойдя до yield, функция отдаёт значение и сохраняет своё состояние. Когда у генератора запрашивают следующее значение, он продолжает точно с того места, где остановился.

return завершает функцию окончательно, а yield только приостанавливает её, поэтому функция может использовать его много раз.

Пример

Генератор, выдающий ряд чисел:

Prompt
Напишите программу на Python, которая определяет генератор count_up_to(n), выдающий числа от 1 до n с помощью цикла while. С помощью цикла for выведите каждое число до 5.
Вывод: полная программа на Python

Генераторы экономят память

Генератор создаёт значения по мере необходимости, а не хранит их все в памяти.

На больших наборах данных это даёт заметную разницу:

Пример

Генератор для очень длинной последовательности:

Prompt
Напишите программу на Python, которая определяет генератор large_sequence(n), выдающий числа от 0 до n-1. Создайте генератор для 1000000 чисел и выведите первые 3 значения с помощью next().
Вывод: полная программа на Python

Использование next() с генераторами

Функция next() позволяет проходить генератор вручную, шаг за шагом.

Когда все значения выданы, следующий вызов приводит к исключению StopIteration.

Пример

Prompt
Напишите программу на Python, которая определяет генератор simple_gen(), выдающий "Emil", "Tobias" и "Linus". Вызовите next() три раза, чтобы вывести каждое значение.
Вывод: полная программа на Python

Пример

Prompt
Напишите программу на Python, которая определяет генератор simple_gen(), выдающий 1 и 2. Вызовите next() три раза, чтобы продемонстрировать исключение StopIteration при третьем вызове.
Вывод: полная программа на Python

Выражения-генераторы

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

Пример

Генератор списка рядом с выражением-генератором:

Prompt
Напишите программу на Python, которая создаёт генератор списка [x * x for x in range(5)] и выводит его. Затем создайте выражение-генератор (x * x for x in range(5)), выведите объект генератора и выведите его значения в виде списка.
Вывод: полная программа на Python

Пример

Передача выражения-генератора в sum:

Prompt
Напишите программу на Python, которая вычисляет сумму квадратов чисел от 0 до 9 с помощью sum() и выражения-генератора. Выведите итог.
Вывод: полная программа на Python

Генератор последовательности Фибоначчи

Последовательность Фибоначчи естественным образом подходит для генератора.

Он может выдавать значения бесконечно, не исчерпывая вашу память:

Пример

Выведите первые 100 чисел Фибоначчи:

Prompt
Напишите программу на Python, которая определяет бесконечный генератор чисел Фибоначчи с помощью yield. Выведите первые 100 чисел Фибоначчи с помощью next().
Вывод: полная программа на Python

Методы генераторов

Для более сложного управления у генераторов есть специальные методы:

Пример

С помощью метода send() можно передать значение в генератор:

Prompt
Напишите программу на Python, которая определяет генератор echo_generator(), получающий значения через yield и выводящий их. Запустите генератор с помощью next(), затем отправьте "Hello" и "World".
Вывод: полная программа на Python

Пример

Метод close() закрывает генератор:

Prompt
Напишите программу на Python, которая определяет генератор my_gen() с блоком try/finally, выдающий 1, 2, 3 и выводящий "Генератор закрыт" в блоке finally. Получите первое значение с помощью next(), затем закройте генератор.
Вывод: полная программа на Python