outside from python generator stopiteration

outside - yield from python



Rendimiento de pitón y stopiteration en un bucle? (2)

Tengo un generador donde me gustaría agregar un valor inicial y final al contenido real, es algo como esto:

# 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

Por supuesto, el código anterior no funciona; mi problema es que me gustaría que no quede nada en la cola, quiero que el generador escupa el footer Y levante el StopIterator . ¿algunas ideas?

Aclamaciones,


Aquí hay un código en el que no se requiere el uso de StopIteration, una interrupción es suficiente:

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

resultado

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

Ahora, aquí hay un código moderadamente complejo en el que me parece que no podemos hacerlo sin usar StopIteration. ¿Te interesa esto?

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)

resultado

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

Tenga en cuenta que este programa se ejecuta correctamente solo con q.get(None) , no con q.get()


Parece que estás complicando demasiado esto:

>>> 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 generará automáticamente cuando un generador deje de producir. Es parte del protocolo de cómo funcionan los generadores. A menos que esté haciendo algo muy complejo, no necesita (y no debe) lidiar con StopIteration en absoluto. Solo tiene que yield cada uno de los valores que desea devolver del generador, luego deje que la función regrese.