You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python协程双yield导致输入丢失问题及正确实现解析

协程输入丢失问题解析及正确实现原理

问题背景

我有一个名为DICTIONARY的字典,键为英文字母,值是对应字母开头的单词,初始内容如下:

DICTIONARY = {
    'a': 'apple',
    'b': 'banana',
    'c': 'cat',
    'd': 'dog',
    ...
}

我需要编写一个名为alphabet的协程,接收字母输入并返回DICTIONARY中对应的单词。

初始协程的问题原因

最初编写的协程使用两个yield语句:

def alphabet():
    while True:
         ch = yield
         yield DICTIONARY[ch]

测试时出现输入丢失,发送'b'返回None,输出不符合预期:

# 测试代码
coro = alphabet()
next(coro)
print(coro.send('a'))  # 输出 apple
print(coro.send('b'))  # 输出 None
print(coro.send('c'))  # 输出 cat

问题出在协程的执行流程上,一步步拆解:

  1. 调用next(coro)时,协程执行到ch = yield,暂停在这里,等待外部发送值。
  2. 第一次send('a'):把'a'赋值给ch,协程继续执行到yield DICTIONARY[ch],返回'apple',此时协程暂停在这个yield语句。
  3. 第二次send('b'):协程从yield DICTIONARY[ch]的位置恢复,进入下一次循环,执行到ch = yield——这里的yield没有附带返回值,所以本次send('b')的返回结果是None,同时把'b'赋值给ch,协程暂停在ch = yield。
  4. 第三次send('c'):把'c'赋值给ch,协程执行到yield DICTIONARY[ch],返回'cat',完成本次循环。

简单说,两个yield导致每次send会交替触发“接收输入”和“返回结果”,中间的一次send只能完成接收,无法返回对应的值,所以出现None。

正确协程的实现原理

修改后的协程用单个yield解决了问题:

# 最终正确的协程实现
def alphabet(letter='a'):
    while True:
        letter = yield DICTIONARY[letter]

它的执行流程是连贯的,每一次send都会完成“接收输入→返回对应结果”的闭环:

  1. 初始化协程coro = alphabet(),调用next(coro):协程执行letter = yield DICTIONARY[letter],先计算右侧的DICTIONARY['a'](因为默认参数是'a'),然后yield返回'apple',协程暂停,此时等待外部发送值来更新letter。
  2. 第一次send('b'):把'b'赋值给letter,协程进入下一次循环,执行letter = yield DICTIONARY[letter],计算DICTIONARY['b']得到'banana',yield返回该值,协程暂停。
  3. 第二次send('c'):把'c'赋值给letter,循环中执行yield DICTIONARY['c']返回'cat',协程暂停。

这个写法的核心是用单个yield同时完成“返回结果”和“接收下一次输入”的操作:每次yield返回当前letter对应的单词,同时等待外部发送的新值来更新letter,下一次循环就用新的letter返回对应结果,完美匹配“输入一个字母→返回对应单词”的需求。


内容的提问来源于stack exchange,提问作者ERJAN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 14:39:58