繁体   English   中英

生成器中的 python3 send() 函数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM