Python协程中yield执行异常:输出与预期不符的原因排查
生成器执行流程分析与问题修正
你的代码:
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
你的理解有遗漏,核心问题是每次send()调用会推进生成器执行到下一个yield语句,并返回该yield产出的值,而你的生成器包含两个yield节点,导致循环中send()的返回值交替对应有效传入值和空产出。
详细执行流程拆解
x = gen():创建生成器对象,未启动。next(x):启动生成器,执行到line3的d = yield(该yield无产出值,默认产出None),生成器在此暂停,等待接收外部传入值。- 第一次循环
i=3,调用x.send(3):- 生成器从line3的暂停处恢复,将
3赋值给d。 - 继续执行到line4的
yield d,产出3,send()方法返回该值,打印3。 - 生成器暂停在line4的
yield d处。
- 生成器从line3的暂停处恢复,将
- 第二次循环
i=4,调用x.send(4):- 生成器从line4的暂停处恢复,执行完line4后回到line2的循环,走到line3的
d = yield。 - 该
yield无产出值(产出None),send()方法返回这个None,打印None。 - 同时将
4赋值给d,生成器暂停在line3的yield处。
- 生成器从line4的暂停处恢复,执行完line4后回到line2的循环,走到line3的
- 第三次循环
i=5,调用x.send(5):- 生成器从line3的暂停处恢复,将
5赋值给d。 - 继续执行到line4的
yield d,产出5,send()方法返回该值,打印5。 - 生成器暂停在line4的
yield d处。
- 生成器从line3的暂停处恢复,将
修正方案
如果要得到预期的3、4、5输出,需要让生成器每次send()对应一次有效产出,调整生成器逻辑即可:
写法一
def gen(): d = None while True: d = yield d # 接收外部值并产出,每次暂停在此处 x = gen() next(x) # 预激生成器,首次产出None可忽略 for i in (3, 4, 5): print(x.send(i))
写法二(更简洁)
def gen(): while True: yield (yield) # 先接收外部值,再产出该值 x = gen() next(x) for i in (3, 4, 5): print(x.send(i))
两种写法都能让每次send(i)返回i,得到你预期的输出结果。
内容的提问来源于stack exchange,提问作者mlz7
相关产品推荐
相关产品推荐

