2017-07-30 106 views
2

這是我的代碼有兩臺發電機定義:發電機可以多次使用嗎?

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 

爲什麼?我認爲任何發電機只能使用一次。

+0

請勿將發電機**功能**與其生成的發電機混淆。 –

+0

換句話說,如果你使用'def one_line_gen():return(x for range in(3))',你的第一個例子將是等價的(每次調用函數時都會生成一個生成器)。 –

+0

密切相關:[Generator Expression vs yield:爲什麼不是'next()'工作?](// stackoverflow.com/q/10958771) –

回答

4

three_line_gen不是一個生成器,它是一個函數。當你稱之爲它時,它返回的是一個生成器,每當你調用它時它就是一個全新的生成器。每次你把括號這樣寫:

three_line_gen() 

這是一個全新的發電機重複使用。然而,如果你是先做

mygen = three_line_gen() 

和迭代mygen兩次,因爲你期望的第二次失敗。

0

因爲在一個班輪是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) 
2

不,你不能迭代發生器兩次。一旦你重複了它,發電機就會耗盡。你會做一個發電機的副本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's answer

0

是的,發電機只能使用一次。但你有兩個發電機對象。

# 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 
0

爲什麼?我認爲任何發電機只能使用一次。

因爲每次調用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]