python yield and stopiteration in one loop?
You seem to be overcomplicating this quite a bit:
>>> 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)something1234anything
StopIteration
will automatically be raised when a generator stops yielding. It's part of the protocol of how generators work. Unless you're doing something very complex, you don't need to (and shouldn't) deal with StopIteration
at all. Just yield
each value you want to return from the generator in turn, then let the function return.
Here's a code in which use of StopIteration isn't required, a break is enough:
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 breakfor y in gen(li): print '1 or 2 digits only:',y
result
1 or 2 digits only: something1 or 2 digits only: 121 or 2 digits only: 511 or 2 digits only: 981 or 2 digits only: 41 or 2 digits only: 361 or 2 digits only: 991 or 2 digits only: 331 or 2 digits only: 11 or 2 digits only: anything
Now, here's a moderately complex code in which it seems to me that we can't do without use of StopIteration. Does this interest you ?
import Queueq = 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 StopIterationprint 'li == %s\n' % lifor i,nb in enumerate(gen(li)): print ' * obtained from enumerate(gen(li)) : %s - %s' % (i,nb)
result
li == [12, 51, 98, 4, 36, 99, 33, 1, 125, 78, 9, 369, 48, 47, 214, 4] * obtained from enumerate(gen(li)) : 0 - somethingq.qsize() first is 5el== 12 * obtained from enumerate(gen(li)) : 1 - 1012q.qsize() second is 5q.qsize() first is 5el== 51 * obtained from enumerate(gen(li)) : 2 - 1051q.qsize() second is 5q.qsize() first is 5el== 98 * obtained from enumerate(gen(li)) : 3 - 1098q.qsize() second is 5q.qsize() first is 5el==4 el//3==1there are 4 items in q and q is emptied 1 times :36 is removed from qq.qsize() second is 3q.qsize() first is 3el== 99 * obtained from enumerate(gen(li)) : 4 - 1099q.qsize() second is 3q.qsize() first is 3el== 33 * obtained from enumerate(gen(li)) : 5 - 1033q.qsize() second is 3q.qsize() first is 3el==1 el//3==0there are 2 items in q and q is emptied 0 times :q.qsize() second is 2q.qsize() first is 2el== 125 * obtained from enumerate(gen(li)) : 6 - 1125q.qsize() second is 2q.qsize() first is 2el== 78 * obtained from enumerate(gen(li)) : 7 - 1078q.qsize() second is 2q.qsize() first is 2el==9 el//3==3there are 1 items in q and q is emptied 3 times :369 is removed from qah !! q is now completely empty, no more emptying is possible ! * obtained from enumerate(gen(li)) : 8 - anything
Note that this program runs correctly only with q.get(None)
, not q.get()
I come from the future. I recommend yield from
:
def gen(q, header="header", footer="footer"): yield header yield from q yield footer
Output:
>>> g = gen([1, 2, 3, 4])>>> print(*g, sep="\n")header1234footer