Проблемы с генераторами python

Я новичок в генераторе в python. У меня есть достаточно простой код, с которым я играю, но я не могу понять вывод, который я получаю. Вот мой код:

def do_gen():
    for i in range(3):
        yield i

def incr_gen(y):
    return y + 1

def print_gen(x):
    for i in x:
        print i

x = do_gen()
y = (incr_gen(i) for i in x)
print_gen(x)
print_gen(y)

Я ожидал, что мой вывод будет таким:

0  1  2 
1  2  3

Но я вижу только:   0 1 2

Я не понимаю этот вывод. Может ли кто-нибудь помочь мне разобраться в моем непонимании? Спасибо заранее.

Ответы

Ответ 1

Генераторы (как и все повторяющиеся) могут быть только повторены один раз. По прошествии времени print_gen(x), то есть x. Любые дальнейшие попытки получить новые значения из x приведут к повышению StopIteration.

Это работает:

x = do_gen()
y = (incr_gen(i) for i in do_gen())
print_gen(x)
print_gen(y)

поскольку это создает два независимых независимых генератора. В вашей версии выражение генератора, присвоенное y, ожидает, что x даст больше значений.

Легче видеть, что генератор x делится с y, когда вы используете по ним функцию next():

>>> def do_gen():
...     for i in range(3):
...         yield i
... 
>>> def incr_gen(y):
...     return y + 1
... 
>>> x = do_gen()
>>> y = (incr_gen(i) for i in x)
>>> next(x)  # first value for the range
0
>>> next(y)  # second value from the range, plus 1
2
>>> next(x)  # third value from the range
2
>>> next(y)  # no more values available, generator done
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Обратите внимание на StopIteration, поднятый next(y), также здесь.