Python生成器核心是暂停恢复机制与迭代器协议封装:yield让函数暂停并保存状态,next()时从断点继续;含yield的函数返回generator对象,支持惰性求值、管道处理和状态维持,但仅单次遍历。

Python生成器的核心原理,其实就两点:暂停恢复机制 + 迭代器协议封装。它不是什么黑魔法,而是对 __iter__ 和 __next__ 的自动化实现,配合 yield 让函数具备“记忆上次执行位置”的能力。
yield 不是 return,是“让出控制权”
每次遇到 yield,函数就暂停,把值交出去,状态(局部变量、执行位置)全保留在栈帧里;下次调用 next() 或进入 for 循环时,从 yield 下一行继续执行。函数不会重新开始,也不会自动结束——直到遇到函数末尾或显式 return(返回的值仅作 StopIteration 的 value 属性,不可被迭代到)。
- 一个函数只要含 yield,定义时就返回 generator 类型对象,不执行函数体
- generator 对象本身是 iterator,但不是 iterable(不能直接 for x in gen_obj,除非它自己实现了 __iter__ —— 实际上 Python 的 generator 对象确实实现了,所以可以)
- 多次调用同一个生成器对象,只能遍历一次;想重用就得重新调用函数创建新对象
生成器表达式:轻量级、惰性求值的列表推导替代品
写法类似 (x*2 for x in range(10) if x % 2 == 0),外层是圆括号。它不构建完整列表,只在每次 next 时算一个值,内存占用恒定 O(1),适合处理大序列或无限流。
- 比等价的生成器函数更简洁,但逻辑复杂时建议用 def + yield,可读性和调试性更好
- 不能用索引、len、切片;只支持单次正向迭代
- 可嵌套:例如
(y for x in data for y in x)实现扁平化
实战中真正有用的技巧
别只盯着“节省内存”,要关注它如何简化代码结构和解耦数据生产与消费逻辑。
立即学习“Python免费学习笔记(深入)”;
-
管道式处理:把多个生成器串起来,如
filter_odd(gen()) | map_square() | take(5),每个环节只关心自己的输入输出,天然支持流式处理 - 状态维持型迭代器:比如解析日志行时需要跨行识别块(如多行堆栈跟踪),用生成器内部维护 state 变量比手动写类更干净
-
协程雏形:通过
gen.send(value)向生成器传参,配合yield接收,就能实现双向通信——这是 asyncio 协程的底层基础之一
容易踩的坑
很多问题源于混淆“生成器对象”和“生成器函数”,或者误以为 yield 能像 return 一样随意控制流程。










