首页 文章

一个循环中的python yield和stopiteration?

提问于
浏览
17

我有一个生成器,我想在实际内容中添加初始值和最终值,它是这样的:

# 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

当然,上面的代码没有留在队列中的任何内容,我希望生成器吐出 footer 并提升 StopIterator . 有任何想法吗?

干杯,

2 回答

  • 7

    你似乎过于复杂了这一点:

    >>> 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 . 它做了非常复杂的事情,你根本不应该处理 StopIteration . 只需要 yield 依次从发生器返回的每个值,然后让函数返回 .

  • 32

    这是一个不需要使用StopIteration的代码,中断就足够了:

    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
    

    结果

    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
    

    现在,这是一个中等复杂的代码,在我看来,我们不能不使用StopIteration . 这对你感兴趣吗?

    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)
    

    结果

    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
    

    请注意,此程序仅在 q.get(None) 正确运行,而不是 q.get()

相关问题