2011-07-22 8 views
16

mam generator gdzie chciałbym dodać wartość początkową i końcową do rzeczywistej treści, to jest coś takiego:wydajność i zatrzymanie Pythona w jednej pętli?

# 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 

Oczywiście, powyższy kod nie działa - moim problemem jest to, że chciałbym, aby tak, że gdy nic nie zostało w kolejce, chcę generator wypluć footer I podnieść StopIterator. jakieś pomysły?

Cheers,

Odpowiedz

30

Wydajesz się być overcomplicating tego sporo:

>>> 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 zostanie automatycznie podniesiony, gdy generator przestaje plonowania. Jest to część protokołu działania generatorów. Jeśli nie robisz czegoś bardzo skomplikowanego, nie musisz (i nie powinieneś) w ogóle zajmować się StopIteration. Tylko yield każda wartość, którą chcesz zwrócić z generatora po kolei, pozwól funkcji wrócić.

+0

yep; Zrobiłem to, komplikując to! dzięki - to załatwiło sprawę. – yee379

+1

Skompilowałem inny kod w podobny sposób ... i uprościłem to dzięki tej odpowiedzi. Dziękuję wam obojgu! –

7

Oto kod, w których nie jest wymagane stosowanie StopIteration, przerwa jest wystarczająco:

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 

wynik

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 

Teraz tutaj jest umiarkowanie skomplikowany kod, w którym wydaje mi się, że nie możemy tego zrobić bez użycia StopIteracji. Czy to cię interesuje?

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) 

wynik

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 

Zauważ, że ten program działa poprawnie tylko z q.get(None) nie q.get()

Powiązane problemy