自python 2.5以来,send()
,throw()
,close()
能够进入生成器。在定义的生成器内部,可以通过执行以下操作来“捕获”发送的数据:
def gen():
while True:
x = (yield)
if x == 3:
print('received 3!!')
break
else:
yield x
我想要玩的是做类似的事情:
def gen2():
while True:
yield (yield)
注意到它是一个合法的发电机做某事.. 我想弄清楚的第一件事是:
这样的写作有用吗?
同样做以下事情:
g = gen2()
next(g)
g.send(10) # output: 10
g.send(2) # output: nothing
g.send(3) # output: 3
g.send(44) # output: nothing
为什么每秒'发送'都没有做任何事情?
答案 0 :(得分:7)
yield (yield)
首先从内部None
获得yield
。然后,它会收到send
或next
的值。内部yield
评估此收到的值,外部yield
立即产生该值。
每个yield
在概念上分为两部分:
send
或next
。send
或next
来电中收到一个值。同样,每个send
或next
在概念上分为两部分:
yield
表达式。 (None
的此值为next
。)yield
表达式中接收值。系统中最令人困惑的部分可能是这些部分交错。 yield
的两个部分对应send
或next
的两个不同调用,send
或next
的两个部分对应两个不同{ {1}}秒。
如果我们通过一个简单的例子:
yield
以下是事情的解决方法:
def gen():
print('Not ran at first')
yield (yield)
g = gen() # Step 1
print(next(g)) # Step 2
print(g.send(1) # Step 3
g.send(2) # Step 4
第1步
Inside the generator Outside the generator
第2步
g calls gen()
g returns a generator object
without executing the print
just yet statement.
>>> g
<generator object gen at 0x7efe286d54f8>
第3步
next(g) sends None to g
g receives None, ignores it
(since it is paused at the start
of the function)
g prints ('not ran at first')
g executes the "transmit" phase
of the inner yield, transmitting
None
next(g) receives None
第4步
g.send(1) sends 1 to g
g executes the "receive" phase
of the inner yield, receiving 1
g executes the "transmit" phase
of the outer yield, transmitting 1
g.send(1) receives 1 from g
答案 1 :(得分:3)
yield
是一个表达式。表达式的值是使用.send
发送的值的值,如果没有发送任何内容,则为None(包括使用next
而不是.send
)。 .send
是方法调用,因此当然也返回一个值,该值是生成器产生的值。换句话说,每次.send
时,都会产生一个值(可能是None),并且每次yield
时,都会发送一个值(可能为None)。
这是一个简单的例子:
def gen():
sent1 = yield 1
print(sent1, "was sent")
sent2 = yield 2
print(sent2, "was sent")
print("Reached end of generator")
g = gen()
print(next(g), "was yielded")
print(g.send("A"), "was yielded")
print(g.send("B"), "was yielded")
next(g)
# output
1 was yielded
A was sent
2 was yielded
B was sent
Reached end of generator
# StopIteration is raised here
在您的示例中,第一个next
产生无,因为第一个yield
是yield (yield)
中的内部产量(即括号中的一个)。第一个send
将10作为值yield
传递。您send
的每个后续值都将成为其中一个收益的值。某些send
调用没有产生输出的原因是内部yield不指定任何值,因此它产生None
。如上所述,当您致电send
时,会产生一个值;在您的情况下,内部yield的值为None,因此在交互式提示符处不显示任何输出。另一方面,外部收益率确定了一个值,即内部收益率的结果。因此,当您send
内部yield
的值时,它将在下一次迭代时由外部yield
产生。 (我假设您在交互式提示符处引用输出;如果您将代码作为脚本运行,则根本不会有输出,因为您从不print
任何内容或以其他方式生成显式内容输出。)
这是另一个可能有启发性的例子:
def gen():
yield (yield (yield (yield "WHOA")))
>>> g = gen()
>>> next(g)
'WHOA'
>>> g.send(1)
1
>>> g.send(2)
2
>>> g.send(3)
3
>>> g.send(4)
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
g.send(4)
StopIteration
请注意,每次发送值时,都会立即返回。这是因为每个yield
都会产生更深层嵌套的yield
的值。每个yield
&#34;变为&#34;发送的值,并立即由链中的下一个yield
产生。这种情况一直持续到所有产量都用尽并且提高了StopIteration。
以前曾有人问过类似的问题。我的印象是,人们期望send
发送&#34;只是发送&#34;一个值。但事实并非如此。使用send
推进生成器并生成下一个结果,就像使用next
一样。您可以将next(gen)
视为等同于gen.send(None)
。