[英]python3 send() function in generators
根据docs , send() 函数:
“恢复执行并将一个值“发送”到生成器函数中。value 参数成为当前 yield 表达式的结果。send() 方法返回生成器生成的下一个值,或者如果生成器退出而没有生成,则引发 StopIteration另一个值。当调用 send() 以启动生成器时,必须以 None 作为参数调用它,因为没有可以接收该值的 yield 表达式。
但我不明白,为什么在下面的例子中没有发生“值参数成为当前产量表达式的结果”:
def gen():
yield 1
x = (yield 42)
print(x)
yield 2
>>>c=gen() #create generator
>>>next(c) #prints '1' and stop execution, which is caused by yield 1
>>>c.send(100) #prints '42', because 'The send() method returns the next value yielded by the generator'
>>>next(c) #prints 'None' and '2'
那么为什么 x 变量保持“无”,尽管我通过 c.send(100) 向它发送了 100? 看起来,右侧的 yield 表达式分两步工作:首先它将值返回给生成器的调用者,然后它返回生成器内部发送函数的参数。 如果在 send(42) 之前添加额外的 next(c),我会得到预期的行为,并且程序会打印“100”。 从文档中我不清楚为什么当我调用 send() 时这两个步骤不应该同时发生。
那么为什么 x 变量保持“无”,尽管我通过 c.send(100) 向它发送了 100?
因为当前的yield
不是您认为的那样,而是之前的yield
。
当您发送 100 时,生成器仍然在yield 1
处停止,而不是在yield 42
,因此 100 将是yield 1
的结果,而不是yield 42
。
为了更清楚地看到这一点,如果您修改生成器以检索z
变量中yield 1
的内容,您将看到z
确实包含 100:
>>> def gen():
... z = yield 1
... x = (yield 42)
... print(x, z)
... yield 2
...
>>> c=gen()
>>> next(c)
1
>>> c.send(100)
42
>>> next(c)
None 100
2
>>>
这就是为什么额外的next()
会打印100
。 回到你的代码:
def gen():
yield 1 # first next(), stops here (before "getting out" of yield)
x = (yield 42) # second next(), stops here (before "getting out" of yield),
# so, when you send(100), then 100 is given to x and execution goes on, so:
print(x) # 100 is printed
yield 2 # ... and 2.
我想我已经想通了。
c = gen()
您在c
变量中创建了一个生成器,生成器的任何代码都不会被执行。
next(c)
然后你使用next()
函数, next
函数转到下一个yield
语句,这里是yield 1
。 所以这个yield
返回1
并停止生成器的执行以尝试捕获一个值。
下一行是c.send(100)
,因此yield 1
正在等待一个值并且您提供了它,但是这个值没有被保存。
send
方法还执行生成器的其余部分,直到下一个yield
语句为:
x = (yield 42)
所以这里的 yield 返回 42 并停止生成器程序以尝试捕获一个值。 但在那之后你打电话
next(c)
而且你没有提供一个值,所以x
现在是 None 。 然后执行剩下的代码(直到下一个yield
语句,不要忘记)
print(x)
yield 2
所以它打印x
who is None 然后yield
返回 2 并尝试捕获一个值。
试试写这个
c = gen()
next(c)
next(c)
c.send(100)
它会起作用(理解为什么!)
来自文档: value 参数成为当前 yield 表达式的结果。 send() 方法返回生成器产生的下一个值。
假设我们有以下无限生成器:
def infgen():
a = 0
while True:
a = yield a
a += 1
generato = infgen()
generato.send(None)
输出:0
.send(None) 的执行与 next() 几乎相同
现在我们有了 a = 0 的第一个值
代码停在这里a = yield a
当value 成为当前 yield 表达式的结果时
yielded 表达式是yield a 。 产生expresion的结果是
generato.send(5)
.send(5) 我们将 5 发送到一个in 生成器并继续:
yielded 表达式的结果是a = 5
一 = 5
+= 1
使用 a = 5 + 1 = 6 转到 while 循环
并停止并产生 a ,其中 a 为 6
输出:6
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.