Когда вызывается какая-либо функция, то выполняются инструкции, содержащиеся в ее определении, а также может быть возвращено любое значение переменной, указанной после ключевого слово return. После завершения работы функции управление передается вызвавшему ее оператору, а состояние функции при этом не сохраняется. При следующем вызове функции она будет обрабатывать те же инструкции от начала до конца еще раз.
В языке Python существует специальная функция-генератор, которая возвращает объект, а не значение. При этом она сохраняет состояние своего последнего вызова и при следующем вызове продолжает работу с той же точки.
Функции-генераторы определяются так же, как и обычные функции, но они дополнительно содержат «генераторную» инструкцию. Она начинается с ключевого слова yield и определяет объект-генератор, который возвращается оператору, вызвавшему функцию. Когда генераторная инструкция исполняется, состояние объекта-генератора «замораживается» и сохраняется. Объект, возвращаемый генераторной инструкцией, может быть присвоен переменной. С помощью встроенной функции next() можно, передав ей имя этой переменной, продолжить выполнение функции с той самой точки заморозки.
Повторный вызов генератора с помощью функции next() продолжает исполнение функции до тех пор, пока не вызовется исключение. Его можно избежать, поместив генераторную инструкцию внутрь бесконечного цикла. Например, чтобы сгенерировать значения с приращением на каждом новом вызове, запишем:
def incrementer():
i = 1
while True:
yield i
i += 1
inc = incrementer()
print(next( inc ))
print(next( inc ))
print(next( inc ))
Эти последовательные вызовы функции выведут целые значения 1, 2 и 3.
Наиболее эффективным будет размещать объект-генератор в цикле, осуществляющем последовательные итерации по значениям.
import random
def lottery():
# возвращает 6 случайных чисел от 1 до 40
for i in range(6):
yield random.randint(1, 40)
# возвращает 7 число от 1 до 15
yield random.randint(1,15)
for random_number in lottery():
print("Следующий номер... %d!" %(random_number))