Что такое генератор

Что такое генератор

Генератор – это итератор, элементы которого можно итерировать только 1 раз

  • Элементы генератора итерируются только 1 раз, потому что они не хранятся в памяти все вместе, а создаются на лету
  • Генераторы это способ реализации итераторов
  • Генератор можно реализовать как функцию или как выражение

Выражение генаратор (Generator Expressions)

Выглядят также как генераторы списка, только не в [] а в ()

my_generator = (i for i in range(10))

Функция генератор

  • Для возврата значения функция использует не return a yield
def generator():
    for i in range(2):
        yield i

# Пример работы 1 
a = generator()
print(next(a)) # 0
print(next(a)) # 1
print(next(a)) # StopIteration

# Пример работы 2
a = generator()

for i in a:
    print(i)
# 1
# 2
def fibon(n):
    a = b = 1
    for i in range(n):
        yield a
        a, b = b, a + b

for x in fibon(10):
    print(x)

В объекте генераторе определены методы iter и next, то есть реализован протокол итератора, то есть по сути любой генератор является итератором. Концептуально, итератор — это механизм поэлементного обхода данных, а генератор позволяет отложено создавать результат при итерации.

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

Ярким пример являются функции range и enumerate:

range генерирует ограниченную арифметическую прогрессию целых чисел, не используя никакой источник данных.

enumerate генерирует двухэлементные кортежи с индексом и одним элементом из итерируемого объекта.

Для начало напишем простой генератор не используя объект-генератор. Это генератор чисел Фибоначчи:
 

class FibonacciGenerator:
    def __init__(self):
        self.prev = 0
        self.cur = 1

    def __next__(self):
        result = self.prev
        self.prev, self.cur = self.cur, self.prev + self.cur
        return result

    def __iter__(self):
        return self

for i in FibonacciGenerator():
    print(i)
    
    if i > 100:
        break

Но используя ключевое слово yield  можно сильно упростить реализацию:

def fibonacci():
    prev, cur = 0, 1
    while True:
        yield prev
        prev, cur = cur, prev + cur

for i in fibonacci():
    print(i)
    if i > 100:
        break

Oct. 8, 2023, Источник

Что такое генератор

В зависимости от контекста, может означать либо функцию-генератор, либо итератор генератора (чаще всего, последнее). Методы __iter__ и __next__ у генераторов создаются автоматически.

С точки зрения реализации, генератор в Python — это языковая конструкция, которую можно реализовать двумя способами: как функция с ключевым словом yield или как генераторное выражение. В результате вызова функции или вычисления выражения, получаем объект-генератор типа types.GeneratorType. Канонический пример - генератор, порождающий последовательность чисел Фибоначчи, которая, будучи бесконечна, не смогла бы поместиться ни в одну коллекцию. Иногда термин применяется для самой генераторной функции, а не только объекта, возвращенного ей в качестве результата.

Так как в объекте-генераторе определены методы __next__ и __iter__, то есть реализован протокол итератора, с этой точки зрения, в Python любой генератор является итератором.

Когда выполнение функции-генератора завершается (при помощи ключевого слова return или достижения конца функции), возникает исключение StopIteration.

Oct. 8, 2023, Источник

Генераторы

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

Oct. 8, 2023, Источник