15

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

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

为什么?我认为任何发电机都只能使用一次。

4

5 回答 5

16

three_line_gen不是生成器,它是一个函数。当你调用它时它返回的是一个生成器,每次你调用它时它都是一个全新的。每次你这样放括号:

three_line_gen()

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

mygen = three_line_gen()

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

于 2017-07-30T12:57:56.430 回答
7

不,您不能对生成器进行两次迭代。一旦你对它进行了迭代,它就会耗尽。您可以使用以下方法制作生成器的副本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)

对于其他问题,请参阅Ofer Sadan 的回答

于 2017-07-30T12:59:24.483 回答
1

为什么?我认为任何发电机都只能使用一次。

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

否则,您是正确的,发电机只会向前运行直到耗尽。

发电机可以多次使用吗?

是的,如果结果在生成器之外缓冲是可能的。一种简单的方法是使用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]
于 2017-08-26T01:16:16.177 回答
1

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

# 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
于 2017-07-30T13:06:55.770 回答
0

因为在一个衬里是GeneratorObject 而三个衬里是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)
于 2017-07-30T12:58:05.070 回答