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.