Генератор - это функция, вызов которой возвращает следующий объект согласно алгоритму.
В отличии от итераторов, для генератора нужно написать лишь функцию, без использования классов.
Напишем функцию-генератор:
Он также будет генерировать рандомные числа от 0 до 1 k раз. Ключевое слово yield говорит о том, что функция является генератором и используется вместо return.
Также стоит отметить, что yield позволяет исполнение кода после своего исполнения, в отличии от return, который останавливает выполнение функции. Что позволяет использовать несколько yield-ов в одном генераторе и писать дополнительные команды после возврата итераций.
Чтоб генератор мог возвращать значения бесконечное(n) количество раз, он должен содержать цикл.
Создадим переменную-генератор, которая будет по сути итератором:
Тип переменной определяется как объект класса 'generator'.
Мы можем проитерировать генератор:
Как видно, разницы результата с итератором нет, но при этом мы имеем более простую конструкцию написания.
Напишем ещё один генератор, который будет иметь конечное количество итераций иметь флаги(print-ы), и попробуем его вручную проитерировать:
Первая итерация, даст первый флаг и первый yield соответственно:
Далее всё понятно:
А вот на третий раз, мы увидим лишь третий флаг, но так как функция является генератором, то также появится исключение StopIteration, аналогично итераторам.
Таким образом, с помощью флагов мы смогли увидеть, что при вызове yield функция останавливается ровно на том месте, на котором оно написано, пока не была вызвана следующая итерация с помощью next() или же цикла перебора.
У генераторов есть особенность, что если использовать ключевое слово return, дойдя до этого места будет брошено исключение StopIteration, после чего будет передано то, что содержал return.
Чтобы проверить это, немного перепишем последний генератор, добавив третий yield, чтобы исключить исключение(извините), и вставим между 2-й и 3-й итераций return, который вернёт строку "Hi":
Также пропишем 3 итерации:
И посмотрим, что получилось:
Как я и сказал выше, return в генераторе дал исключение StopIteration с аргументами, которые были в него переданы.