【问题标题】:sending and receiving values on the same generator在同一个生成器上发送和接收值
【发布时间】:2012-11-17 13:19:09
【问题描述】:

我正在尝试了解 python 生成器的一些微妙细节。我编写的一个测试程序,看看我是否可以向/从同一个生成器交替发送和读取值,如下所示:

def injector():
    while True:
        try:
            print 'a'
            v = yield
            print 'b', v
            yield v
            print 'c'
        except GeneratorExit:
            print 'exit'
            break

g = injector()

print 'send none'
g.send(None)
print 'send 2'
g.send(2)
print 'receiving'
v = g.next()
print 'received', v

g.close()

这个程序的预期输出是:

send none
a
send 2
b 2
receiving
received 2
c
a
exit

我得到的输出是:

send none
a
send 2
b 2
receiving
c
a
received None
exit

现在,很明显,问题是为什么我会得到上述输出?关于生成器的工作原理,我有什么不明白的地方?

【问题讨论】:

    标签: python generator coroutine


    【解决方案1】:

    让我试着澄清一下:

    def injector():
        while True:
            try:
                print 'a'
                v = yield
                print 'b', v
                yield v
                print 'c'
            except GeneratorExit:
                print 'exit'
                break
    
    g = injector()
    
    print 'send none'
    g.send(None)
    

    协程在这里启动。它一直执行到第一个 yield 的结果从.send() 返回,然后被丢弃。

    协程打印a 并没有产生任何结果,因此None。所以丢弃是可以的。

    print 'send 2'
    g.send(2)
    

    在这里,您向协程发送 2,使其从您离开的地方继续。 v = 2.

    它打印2 并再次生成v。您会期望从g.send() 电话中获得这一点。 所以在接收和丢弃v之后,你做

    print 'receiving'
    v = g.next()
    

    在这里,您再次将控制权交给协程,它会打印c,然后是a,然后再次产生None,您可以在这里得到。

    print 'received', v
    

    因此为v打印None

    你可能想要的是

    g = injector()
    
    print 'send none'
    g.send(None)
    print 'send 2'
    v = g.send(2)
    print 'received', v
    
    g.close()
    

    (请注意,最后一个块可以写得更干净漂亮,如下所示:

    from contextlib import closing
    with closing(injector()) as g:
        print 'send none'
        g.send(None)
        print 'send 2'
        v = g.send(2)
        print 'received', v
    

    )

    【讨论】:

    【解决方案2】:

    所以,您遇到的问题是最后一次通话。首先,它似乎从代码停止的地方开始,首先打印'c'。然后由于该语句没有产生,它在while循环中继续,打印'a'。最后,产生输出。 none 结果是因为在'a' 之后没有产生任何结果

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-22
      • 1970-01-01
      • 2012-10-05
      • 1970-01-01
      • 2017-10-25
      • 2015-11-22
      相关资源
      最近更新 更多