我试图了解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
现在,显然,问题是为什么我得到上述输出?什么是我不了解发电机如何工作?
答案 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'