在同一台发电机上发送和接收值

时间:2012-11-29 12:52:04

标签: python generator coroutine

我试图了解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

现在,显然,问题是为什么我得到上述输出?什么是我不了解发电机如何工作?

2 个答案:

答案 0 :(得分:3)

让我试着澄清一下:

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
因此,

None打印v

你可能想要的是

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

答案 1 :(得分:0)

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

之后没有产生任何结果