发电机可以多次使用吗?

Can generator be used more than once?

这是我定义了两个生成器的代码:

one_line_gen = (x for x in range(3))

def three_line_gen():
    yield 0
    yield 1
    yield 2

当我执行时:

for x in one_line_gen:
    print x

for x in one_line_gen:
    print x

结果符合预期:

0
1
2

但是,如果我执行:

for x in three_line_gen():
    print x

for x in three_line_gen():
    print x

结果是:

0
1
2
0
1
2

为什么?我还以为任何生成器都只能用一次

three_line_gen 不是生成器,它是一个函数。你叫它returns的时候它是一个发电机,每次叫它都是一个全新的。每次你像这样放置括号:

three_line_gen()

这是一个全新的迭代生成器。但是,如果您要先做

mygen = three_line_gen()

并迭代 mygen 两次,第二次将如您所料失败。

因为在一个衬里是Generator对象而三个衬里是一个function。 他们本来就是不同的。

这两个很相似。

def three_line_gen_fun():
    yield 0
    yield 1
    yield 2

three_line_gen = three_line_gen_fun()
one_line_gen = (x for x in range(3))

type(three_line_gen) == type(one_line_gen)

不,您不能对生成器进行两次迭代。一旦你迭代了它,一个生成器就会耗尽。你可以用 tee 制作一个生成器的副本:

from itertools import tee

one_line_gen = (x for x in range(3))
gen1, gen2 = tee(one_line_gen)
# or: 
# gen1, gen2 = tee(x for x in range(3))

for item in gen1:
    print(item)

for item in gen2:
    print(item)

其他问题见

是的,发电机只能使用一次。但是你有两个生成器对象。

# Python 3


def three_line_gen():
    yield 0
    yield 1
    yield 2

iterator = three_line_gen()
print(iterator)
for x in iterator:
    print(id(iterator), x)

iterator2 = three_line_gen()
print(iterator2)
for x in iterator2:
    print(id(iterator2), x)

结果是:

<generator object three_line_gen at 0x1020401b0>
4328784304 0
4328784304 1
4328784304 2
<generator object three_line_gen at 0x1020401f8>
4328784376 0
4328784376 1
4328784376 2

Why? I thought any generator can be used only once.

因为每次调用 three_line_gen() 都会创建一个新的生成器。

否则,你是正确的,发电机只 运行 前进直到耗尽。

Can generator be used more than once?

是的,如果结果在生成器外部进行缓冲,这是可能的。一种简单的方法是使用 itertools.tee():

>>> from itertools import tee
>>> def three_line_gen():
        yield 0
        yield 1
        yield 2

>>> t1, t2 = tee(three_line_gen())
>>> next(t1)
0
>>> next(t2)
0
>>> list(t1)
[1, 2]
>>> list(t2)
[1, 2]