2016-08-23 76 views
0

爲了說明這個問題,假設我們有這個簡單的發電機:當發生器運行的值不足以產生時會發生什麼?

def firstn(n): 
    num = 0 
    while num < n: 
     yield num 
     num += 1 

for i in firstn(10): 
    print i 

這將打印數字0到9。但是,如果我們有:

def firstn(n): 
    num = 0 
    while num < 5 < n: 
     yield num 
     num += 1 

for i in firstn(10): 
    print i 

(變化是在while語句)。然後它只打印數字0到4.一旦num >= 5,那麼生成器不再產生值。

我很好奇的是引擎蓋下發生的事情:我用PythonTutor單步執行代碼,和印象,我下的是,一旦while語句不再True,該函數返回隱None ,其中for循環以某種方式檢測,然後也中斷。我用next內置到這種更仔細檢查:

>>> def firstn(n): 
...  num = 0 
...  while num < 5 < n: 
...   yield num 
...   num += 1 
... 
>>> 
>>> mygen = firstn(100) 
>>> next(mygen) 
0 
>>> next(mygen) 
1 
>>> next(mygen) 
2 
>>> next(mygen) 
3 
>>> next(mygen) 
4 
>>> next(mygen) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 

支持我的理論。我的一個大問題是:StopIteration是如何工作的,這是否意味着調用一個大值的生成器可以等價於用它最小的終止值調用它?在我們的例子中,for i in firstn(5)for i in firstn(9999999999999)應該是等價的,對嗎?

+0

你知道,'NUM <5 jwodder

+0

對於第二種情況,是的。無論你通過什麼,只要它大於5,它就會返回1..4。一旦一個生成器用完了值,就會引發一個'StopIteration'異常,它告訴調用者它的數據用完了。 –

回答

1

這不是很神祕。當一個發生器用完值時,它會產生一個StopIteration異常。您只需要瞭解for循環在Python中的工作方式。本質上,它是等效於以下代碼:

iterator = iter(collection) 
while True: 
    try: 
     x = next(iterator) 
     # do something 
    except StopIteration as e: 
     break 

以上是等效於:

for x in collection: 
    # do something 
+0

很酷。我不知道for循環使用了'StopIteration'來打破。謝謝。 – Newb

+0

@Newb不要被欺騙,但這只是等效的Python。在引擎蓋下,它是一個更加優化的C實現(在CPython中)。 –