2011-07-22 31 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()