python yield and stopiteration in one loop?

后端 未结 2 882
温柔的废话
温柔的废话 2021-02-07 02:52

i have a generator where i would like to add an initial and final value to the actual content, it\'s something like this:

# any generic queue where i would like          


        
相关标签:
2条回答
  • 2021-02-07 03:04

    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
                break
    
    for y in gen(li):
        print '1 or 2 digits only:',y
    

    result

    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
    

    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 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)
    

    result

    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
    

    Note that this program runs correctly only with q.get(None) , not q.get()

    0 讨论(0)
  • 2021-02-07 03:21

    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)
    
    
    something
    1
    2
    3
    4
    anything
    

    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.

    0 讨论(0)
提交回复
热议问题