yield и функции-генераторы

Инструкция yield в Python является одной из мощных и гибких возможностей языка, предназначенной для создания функций-генераторов (не путать с выражениями-генераторами списков!). Генераторы позволяют создавать итераторы простым и лаконичным способом, экономя память и повышая производительность программ.

Инструкция yield

Инструкция yield используется внутри функции для превращения её в генератор. В отличие от обычных функций, генераторы возвращают значение, но сохраняют своё состояние между вызовами, что позволяет возобновить выполнение с того места, где они были прерваны.

def simple_generator():
    yield 1
    yield 2
    yield 3

gen = simple_generator()

print(next(gen))  # Выведет 1
print(next(gen))  # Выведет 2
print(next(gen))  # Выведет 3

Особенности использования yield

  • Сохранение состояния: Генераторы сохраняют своё состояние между вызовами, что позволяет им продолжить выполнение с места, где они были прерваны
  • Ленивые вычисления: Генераторы производят значения только "по требованию", что экономит память. Это особенно полезно при работе с большими данными или бесконечными последовательностями. Однако ошибки внутри функции могут появиться в середине вашего цикла for, а не сразу при вызове функции
  • Автоматическое управление состоянием: Использование генераторов позволяет избежать необходимости в явном управлении состоянием и использовании вспомогательных переменных или структур данных

Примеры использования yield

Создание простого счетчика:

def counter():
    count = 0
    while True:
        yield count
        count += 1

count_gen = counter()
print(next(count_gen))  # 0
print(next(count_gen))  # 1
print(next(count_gen))  # 2

Создание последовательности чисел Фибоначчи от 1 до n:

def fibonacci(n):
    a, b = 0, 1
    for i in range(n):
        yield a
        a, b = b, a + b

fib_gen = fibonacci(10)
for i in fib_gen:
    print(i)

Функции, в которых есть yield, возвращают итератор. Тот самый, который можно помещать внутрь цикла for.

Можно и вручную вызывать следующий элемент функцией next, что и было продемонстрировано в примерах выше.

Различия между yield и return

return завершает выполнение функции и возвращает значение.

yield приостанавливает выполнение функции и возвращает значение, сохраняя текущее состояние функции для последующего возобновления.

При этом в функции-генераторе могут встречаться return для досрочного завершения работы генератора (обычно при каких-то условиях).