yield使函数变为生成器,每次next()执行到yield暂停并保存状态,下次从中断处继续;支持send双向通信、yield from委托子生成器,本质是编译器实现的状态机。

yield 关键字让函数变成生成器,每次调用 next() 时执行到下一个 yield,暂停并返回值,状态(局部变量、执行位置等)被保留,下次继续从暂停处运行。
yield 是“暂停点”,不是 return
普通函数遇到 return 就彻底结束;而 yield 让函数“挂起”——执行上下文(栈帧)被保存,函数并未退出。下一次调用生成器的 next() 方法时,它从 yield 后面那行代码继续执行,而非重新开始。
- 第一次调用
next():运行到第一个 yield,返回其右侧表达式的值,然后暂停 - 第二次调用
next():从 yield 后恢复,继续执行直到下一个 yield 或函数结束 - 函数自然返回或 raise StopIteration 时,生成器终止
生成器对象内部维护执行状态
调用生成器函数(如 gen = countdown(3))并不执行函数体,只创建一个生成器对象。这个对象内部封装了闭包环境、指令指针(当前执行到哪条字节码)、局部变量等。每次 next(gen) 实际是驱动这个状态机向前一步。
- 局部变量不会在 yield 后丢失,比如计数器 i 在多次 yield 间保持递减
- 函数作用域仍活跃,所有闭包绑定变量均可访问
- Python 解释器通过生成器帧对象(
gen.gi_frame)管理该状态
yield 可双向通信:接收外部传入值
yield 不仅能产出值,还能通过 generator.send(value) 接收值。send 会唤醒暂停的生成器,并把 value 赋给当前 yield 表达式左侧(即 yield 本身可作为表达式参与赋值)。
-
x = yield y:先产出 y,暂停;恢复时,外部 send 的值赋给 x - 首次调用必须用
next()或send(None)启动(因为还没到能接收值的位置) - 这使得生成器可充当协程,实现用户态的协作式调度
yield from 委托子生成器
当需要将控制权委托给另一个生成器时,yield from subgen 不仅逐个产出 subgen 的值,还自动转发 send、throw、close 等操作,让外层生成器与子生成器形成透明通道。
- 避免手动循环 + yield 每个值,减少样板代码
- 子生成器的 return 值会成为 yield from 表达式的返回值(需捕获 StopIteration)
- 异常和关闭信号也能穿透传递,适合构建生成器管道











