2011-07-22 74 views
16

我有一臺發電機在這裏我想一個初始值和最終值添加到實際的內容,它是這樣的:在一個循環中python yield和stopiteration?

# any generic queue where i would like to get something from 
q = Queue() 

def gen(header='something', footer='anything'): 
    # initial value header 
    yield header 

    for c in count(): 
     # get from the queue 
     i = q.get() 
     # if we don't have any more data from the queue, spit out the footer and stop 
     if i == None: 
      yield footer 
      raise StopIteration 
     else: 
      yield i 

當然,上面的代碼不工作 - 我的問題是,我會喜歡這樣,當隊列中沒有任何東西時,我想要發電機吐出footer並提高StopIterator。有任何想法嗎?

乾杯,

回答

30

你似乎過於複雜這頗有幾分:

>>> q = [1, 2, 3, 4] 
>>> def gen(header='something', footer='anything'): 
     yield header 
     for thing in q: 
      yield thing 
     yield footer 


>>> for tmp in gen(): 
     print(tmp) 


something 
1 
2 
3 
4 
anything 

StopIteration當發生器停止產生會自動升起。它是發電機工作原理的一部分。除非你做的事情非常複雜,否則根本不需要(也不應該)處理StopIteration。只需要yield每個要依次從發生器返回的值,然後讓函數返回。

+0

是的;我確實讓它複雜化了!謝謝 - 這就是訣竅。 – yee379

+1

我以類似的方式過度複雜化了另一個代碼...並簡化了它,感謝這個答案。謝謝你們兩位! –

7

這裏是在不需要使用的StopIteration的代碼,休息就夠了:

li = [12,51,98,4,36,99,33,1,125,78,9,369,48,47,214,4] 

def gen(cont, header='something', footer='anything'): 
    yield header 
    for x in cont: 
     if x<100: 
      yield x 
     else: 
      yield footer 
      break 

for y in gen(li): 
    print '1 or 2 digits only:',y 

結果

1 or 2 digits only: something 
1 or 2 digits only: 12 
1 or 2 digits only: 51 
1 or 2 digits only: 98 
1 or 2 digits only: 4 
1 or 2 digits only: 36 
1 or 2 digits only: 99 
1 or 2 digits only: 33 
1 or 2 digits only: 1 
1 or 2 digits only: anything 

現在,這裏是一個比較複雜的代碼,這在我看來,我們不能使用StopIteration。這對你感興趣嗎?

import Queue 
q = Queue.Queue() 

li = [12,51,98,4,36,99,33,1,125,78,9,369,48,47,214,4] 

def gen(cont, header='something', footer='anything'): 
    def qput(ili = [0]): 
     eli = li[ili[0]] 
     q.put(eli) 
     ili[0] = ili[0] + 1 
     return eli 

    qput() 
    qput() 
    qput() 
    qput() 
    qput() 
    yield header 

    while True: 
     try: 
      print '\nq.qsize() first is %s' % q.qsize() 

      el = q.get(None) 

      if el>9: 
       print 'el==',el 
       yield 1000+el 
       qput() 
      else: 
       print 'el==%s el//3==%s' % (el,el//3) 
       print 'there are %s items in q and q is emptied %s times :' % (q.qsize(),el//3) 
       for emp in xrange(el//3): 
        print '%s is removed from q' % q.get(None) 
        if q.qsize()==0 and emp<el//3: 
         print 'ah !! q is now completely empty, no more emptying is possible !' 

      print 'q.qsize() second is %s' % q.qsize() 

     except Queue.Empty: 
      yield footer 
      raise StopIteration 


print 'li == %s\n' % li 
for i,nb in enumerate(gen(li)): 
    print ' * obtained from enumerate(gen(li)) : %s - %s' % (i,nb) 

結果

li == [12, 51, 98, 4, 36, 99, 33, 1, 125, 78, 9, 369, 48, 47, 214, 4] 

* obtained from enumerate(gen(li)) : 0 - something 

q.qsize() first is 5 
el== 12 
* obtained from enumerate(gen(li)) : 1 - 1012 
q.qsize() second is 5 

q.qsize() first is 5 
el== 51 
* obtained from enumerate(gen(li)) : 2 - 1051 
q.qsize() second is 5 

q.qsize() first is 5 
el== 98 
* obtained from enumerate(gen(li)) : 3 - 1098 
q.qsize() second is 5 

q.qsize() first is 5 
el==4 el//3==1 
there are 4 items in q and q is emptied 1 times : 
36 is removed from q 
q.qsize() second is 3 

q.qsize() first is 3 
el== 99 
* obtained from enumerate(gen(li)) : 4 - 1099 
q.qsize() second is 3 

q.qsize() first is 3 
el== 33 
* obtained from enumerate(gen(li)) : 5 - 1033 
q.qsize() second is 3 

q.qsize() first is 3 
el==1 el//3==0 
there are 2 items in q and q is emptied 0 times : 
q.qsize() second is 2 

q.qsize() first is 2 
el== 125 
* obtained from enumerate(gen(li)) : 6 - 1125 
q.qsize() second is 2 

q.qsize() first is 2 
el== 78 
* obtained from enumerate(gen(li)) : 7 - 1078 
q.qsize() second is 2 

q.qsize() first is 2 
el==9 el//3==3 
there are 1 items in q and q is emptied 3 times : 
369 is removed from q 
ah !! q is now completely empty, no more emptying is possible ! 
* obtained from enumerate(gen(li)) : 8 - anything 

注意,這個程序只用q.get(None)正常運行,不q.get()