在协程内部实现“yield”。

3

我有以下代码。

def gen():
    while True:        # line 2
        d = yield      # line 3
        yield d        # line 4

x = gen()
next(x)

for i in (3, 4, 5):
    print(x.send(i))   # line 10

当我运行这个程序时,会得到如下结果:
3
None
5

而不是:

3
4
5

这正是我所期望的。我已经阅读了几个类似的问题(包括这个),但我仍然不明白这里发生了什么。

我的理解如下: 我们通过调用next(x)来启动生成器,它开始执行并进入第2行的while循环。在第3行上,我们有一个yield语句,执行暂停。在第10行,我们发送值3。执行在第3行恢复,将d设置为3,然后我们返回d。在第10行,send返回产生的值(3)。生成器继续执行,直到回到第3行的yield语句,等等。

是否有错误?我在这里做错了什么?


为什么要使用两个 yield - Kelly Bundy
1
但是 两者都 返回一个值... - Kelly Bundy
@KellyBundy,您介意详细说明一下吗?虽然我在这方面还比较新,但我认为 d = yield 本质上是用于接收传入数据(在有数据可用之前会阻塞),而 yield d 用于生成传出数据。 - mlz7
1
@Axe319 啊,我明白了。所以 d = yield 总是默认隐式地 yield None - mlz7
2
这不仅仅是“可以同时执行两个操作” - 你总是同时执行两个操作,但例如 yield d 不会保存它接收到的内容,而 d = yield 则会产生 None 值并接收一个值。 - zvone
显示剩余3条评论
1个回答

1

x = yield y 做了两件事:

  1. 返回 y
  2. 将下一个发送的值赋给 x

如果没有 y,则返回 None。如果没有 x =,则发送的值将会被丢弃。

所以这里发生的是:

code         effects         comments
---------------------------------------------
d = yield    return None     ok, you ignore it
             d = 3
yield d      return 3        gets printed
             Throw away 4
d = yield    return None     gets printed
             d = 5
yield d      return 5        gets printed

你可以像这样修复它,始终存储并返回每个发送的值:
def gen():
    d = None  # or `d = yield`, either works, just differently
    while True:
        d = yield d

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接