2011-07-22 9 views
16

tengo un generador donde te gustaría añadir un valor inicial y final para el contenido real, es algo como esto:rendimiento de pitón y la detención en un ciclo?

# 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 yo me gustaría que cuando no quede nada en la cola, quiero que el generador escupe el footer Y eleve el StopIterator. ¿algunas ideas?

Saludos,

Respuesta

30

Usted parece ser complicar esto un poco:

>>> 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 se elevará automáticamente cuando se detiene un generador de rendimiento. Es parte del protocolo de funcionamiento de los generadores. A menos que esté haciendo algo muy complejo, no necesita (y no debe) tratar con StopIteration en absoluto. Simplemente yield cada valor que desee devolver del generador, luego, deje que la función vuelva.

+0

sí; lo hice más complicado! gracias - eso hizo el truco. – yee379

+1

He sobrecomplicado otro código de una manera similar ... y lo simplifiqué gracias a esta respuesta. Gracias a los dos ! –

7

Aquí hay un código en el que no se requiere el uso de StopIteration, un descanso 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 hacer sin usar StopIteration. ¿Esto te interesa?

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 sólo con q.get(None), no q.get()

Cuestiones relacionadas