生成器是可被外部主动干预的执行单元,yield既能返回值又能接收值,通过send()传入指令改变状态、throw()强制中断、yield from实现跨层注入。

生成器本身不是被动“产出”的容器,而是可被外部主动干预的执行单元。关键在于 yield 不仅能返回值,还能接收值——这个接收动作就是外部干扰注入的入口。
yield 接收值是干扰注入的前提
每次 yield x 执行时,生成器暂停,并把 x 返回给调用方;下一次调用 send(value) 时,value 会直接赋给这个 yield 表达式所在的位置,从而改变内部变量或跳转逻辑。
- 首次必须用
next(gen)或gen.send(None)启动,否则没有 yield 可接收值 -
yield必须出现在赋值语句右侧,例如cmd = yield result,才能让外部传入的值落进cmd - 如果写成
yield x单独一行,外部传入的值会被丢弃(但执行仍会继续)
用 send() 改变状态或触发分支
把生成器当作一个带状态的协程,通过外部传入的指令控制其行为走向:
- 传入字符串命令,如
"pause"、"reset"、"skip",在生成器内用if判断并响应 - 传入数字调整参数,比如步长、阈值、重试次数,实现运行时动态调优
- 传入布尔值开关某段逻辑,例如是否启用日志、是否跳过校验
示例片段:
def stateful_processor():count = 0
while True:
action = yield f"processed {count}"
if action == "reset":
count = 0
elif action == "inc":
count += 1
else:
count += 2
用 throw() 强制中断或切换上下文
当需要非协作式干扰——比如立即终止当前流程、回滚状态、进入错误处理路径——throw() 是更直接的方式:
-
gen.throw(StopProcessingError)可触发生成器内部的except StopProcessingError块 - 配合
finally,确保无论是否异常,资源(如文件、连接)都能释放 - 抛出自定义异常类型,让生成器根据异常类型执行不同清理或恢复逻辑
yield from 实现跨层注入
若生成器委托了子生成器(yield from sub_gen),所有 send()、throw()、close() 都会自动透传到底层:
- 外部对主生成器调用
send("retry"),实际由子生成器接收并处理 - 主生成器无需解包或中转,天然支持多级嵌套下的统一控制接口
- 适合构建流水线式结构,例如 “解析 → 校验 → 转换”,每层都可被独立干预

















