2011-01-19 75 views
110

我有類似以下的發電機功能:如何從發生器中挑選一個項目(在python中)?

def myfunct(): 
    ... 
    yield result 

的常用方法來調用這個函數是:

for r in myfunct(): 
    dostuff(r) 

我的問題,是有沒有辦法從發電機得到的只是一個元素每當我喜歡? 例如,我想這樣做:

while True: 
    ... 
    if something: 
     my_element = pick_just_one_element(myfunct()) 
     dostuff(my_element) 
    ... 

回答

161

創建使用

g = myfunct() 

每當你想的項目的生成,使用

g.next() 

next(g) 

如果發電機退出,它會增加StopIteration。您可以在必要時捕獲這個異常,或者使用default參數next()

next(g, default_value) 
+3

請注意,只有在g中的最後一項提供後嘗試使用g.next()時,它纔會引發StopIteration。 – Wilduck 2011-01-19 22:11:08

+15

`next(gen,default)`也可以用來避免`StopIteration`異常。例如,對於一個字符串生成器,`next(g,None)`在迭代完成後將產生一個字符串或None。 – Attila 2013-03-06 14:18:08

+4

在Python 3000中,next()是__next __() – 2014-04-10 02:52:09

-1

我認爲唯一的辦法是讓從迭代器列表,然後讓你從列表中選擇所需的元素。

l = list(myfunct()) 
l[4] 
2

我不相信有一種方便的方法來從發生器檢索任意值。生成器將提供next()方法來遍歷自己,但不會立即生成完整序列以節省內存。這是生成器和列表之間的功能差異。

0
generator = myfunct() 
while True: 
    my_element = generator.next() 

確保抓取

12

對於在for聲明發電機使用break的一個元素採摘的最後一個元素後拋出的異常,或list(itertools.islice(gen, 1))

根據你的榜樣(你可以這樣做:

while True: 
    ... 
    if something: 
     for my_element in myfunct(): 
      dostuff(my_element) 
      break 
     else: 
      do_generator_empty() 

如果你想「得到理由從 [一旦產生] 發生器每當我喜歡「t的一個元件(I假設50%這就是初衷,和最常見的意圖),那麼:

gen = myfunct() 
while True: 
    ... 
    if something: 
     for my_element in gen: 
      dostuff(my_element) 
      break 
     else: 
      do_generator_empty() 

這種方式顯式使用的generator.next()可以是避免,並且輸入結束處理不需要(神祕的)異常處理或額外的默認值比較。

for語句部分僅在需要在發生器結束時做一些特殊的事情時才需要。在next()/.next()

注:

在Python3的.next()方法更名爲.__next__()有很好的理由:它被認爲是低級別(PEP 3114)。在Python 2.6之前,內置函數next()不存在。甚至還有人討論將next()轉移到operator模塊(這將是明智的),因爲它很少需要和可疑的內置名稱通脹。

沒有默認使用next()仍然是非常低級的做法 - 在正常的應用程序代碼中,像普通應用程序代碼中的螺栓一樣拋出神祕的StopIteration。並且使用next()與默認定點 - 最好應該是直接在builtins中的next()的唯一選項 - 是有限的,並且經常給出奇怪的非pythonic邏輯/可讀性的原因。底線:使用next()應該是非常罕見的 - 就像使用operator模塊的函數一樣。使用for x in iterator,islice,list(iterator)和其他無縫接受迭代器的函數是在應用程序級別上使用迭代器的自然方式 - 而且總是可能的。 next()是低級的,一個額外的概念,不明顯 - 正如這個線程的問題所示。雖然例如在for中使用break是常規的。

相關問題