Python 迭代器与生成器
可迭代对象提供迭代器;迭代器实现 __next__;生成器用 yield 惰性产出状态机。
#type / concept
#status / growing
#tech / dev
#resource / python
#tech / lang / python
[!info] 关联笔记
Python 迭代器与生成器
这个概念为什么出现
for 能遍历文件行、查询结果、无限流,是因为迭代协议,不是因为它们都是 list。生成器让你用同步写法表达惰性流水线,避免一次装入内存。
[!abstract] 一句话理解 可迭代对象通过
__iter__返回迭代器;迭代器通过__next__产出元素并在结束时抛StopIteration;yield函数是生成器迭代器。
最小可运行示例
先把示例放进业务场景,再看代码:
场景:按批次惰性产出待同步订单 ID
# order_batches_gen.py
# 业务意图:把大列表切成固定批次,惰性产出。
# 教学点:
# - yield 生成器;
# - for 消费迭代器;
# - 耗尽后不可再取。
from typing import Iterator, Sequence
def batched(items: Sequence[str], size: int) -> Iterator[list[str]]:
if size <= 0:
raise ValueError("size must be positive")
for i in range(0, len(items), size):
yield list(items[i : i + size])
def main() -> None:
orders = [f"O{i}" for i in range(1, 6)]
gen = batched(orders, 2)
print(next(gen))
print(next(gen))
print(list(gen)) # 剩余批次
if __name__ == "__main__":
main()
建议运行:
python order_batches_gen.py
期望输出:
['O1', 'O2']
['O3', 'O4']
[['O5']]
结合场景再看三个关注点
- 批次按需产出,适合同步任务队列。
next与 for 都在推进同一迭代器状态。- 生成器是一次性的;要重跑需重新调用函数。
核心概念与准确模型
flowchart LR
Iterable -->|"iter()"| Iterator
Iterator -->|"next()"| Item
Iterator -->|"end"| StopIteration
iter(x)/next(it, default)- 生成器函数、生成器表达式
yield from委托子迭代器
边界情况与反直觉行为
- list 是可迭代也可反复遍历;生成器不行。
- 在生成器内 return value 变成
StopIteration.value(少直接依赖)。 - 生成器 close/throw 用于协程风格控制(进阶)。
常见误区
[!warning] 常见误区:把生成器当列表返回多次使用 错误理解:变量里装着全部数据。
正确模型:装着“如何继续算”的状态机。
工程实践
- 大文件按行迭代
- 流水线:生成器链接
- 需要多遍消费时
list(gen)或重开
本节总结
迭代协议统一了 for 的世界;生成器是最省事的惰性工具。
自测题
- 可迭代与迭代器差别?
- 为什么
list(gen)后 gen 空了?
参考答案
- 可迭代能提供迭代器;迭代器保持遍历位置并 next。
- 迭代器已耗尽。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Iterator types | 文档 | 协议 |
| Yield expressions | 规范 | yield |