第14章 生成器与迭代器
第14章 生成器与迭代器
学习目标
完成本章学习后,读者应能够:
- 理解迭代协议:掌握迭代器协议(
__iter__/__next__)与可迭代协议(__iter__)的设计原理与实现机制 - 精通生成器函数:深入理解
yield的执行模型、生成器状态机、协程式通信(send/throw/close) - 运用
yield from:理解子生成器委托机制及其在异步编程中的基础作用 - 掌握生成器表达式:理解惰性求值的内存优势与适用场景
- 运用itertools:熟练使用标准库迭代器工具构建高效的数据处理管道
- 设计迭代器架构:能够为实际项目设计自定义迭代器,处理无限序列、数据流管道等场景
14.1 迭代协议与底层机制
14.1.1 迭代器协议
Python的迭代基于两个核心协议:
- 可迭代协议(Iterable Protocol):对象实现
__iter__()方法,返回一个迭代器 - 迭代器协议(Iterator Protocol):对象实现
__next__()方法,返回下一个元素;元素耗尽时抛出StopIteration
1 | from collections.abc import Iterable, Iterator |
关键理解:迭代器自身也是可迭代的(__iter__返回self),但可迭代对象不一定是迭代器。例如列表是可迭代的,但不是迭代器——每次调用iter(list)都返回一个新的迭代器对象。
1 | my_list = [1, 2, 3] |
14.1.2 for循环的底层机制
for循环的本质是调用iter()获取迭代器,然后反复调用next()直到StopIteration:
1 | def manual_for(iterable, func): |
14.1.3 分离可迭代对象与迭代器
最佳实践是将可迭代对象和迭代器分离为两个类。这样可迭代对象可以多次迭代,每次创建独立的迭代器:
1 | class Range: |
14.1.4 迭代器的常见陷阱
迭代器只能消费一次:
1 | it = iter([1, 2, 3]) |
迭代器不是序列:迭代器不支持len()、索引和切片,因为它可能是无限的或长度未知的。
1 | it = iter([1, 2, 3]) |
14.2 生成器函数
14.2.1 yield的执行模型
生成器函数是包含yield语句的函数。调用生成器函数不会执行函数体,而是返回一个生成器对象。每次调用next()时,函数从上次暂停的位置恢复执行,直到遇到下一个yield或函数结束。
1 | def simple_generator(): |
生成器的内部状态:
1 | import inspect |
生成器状态有四种:
GEN_CREATED:已创建但尚未启动GEN_RUNNING:正在执行(多线程中可见)GEN_SUSPENDED:在yield处暂停GEN_CLOSED:已关闭
14.2.2 生成器与协程
生成器不仅是迭代器,还是协程(Coroutine)的基础。通过send()、throw()和close()方法,生成器可以接收外部输入、处理异常和响应关闭请求。
send方法:向生成器发送值,该值成为yield表达式的结果:
1 | def accumulator(): |
协程式生成器模式:send使生成器成为数据消费者而非仅是生产者:
1 | def processor(): |
throw方法:在生成器暂停处抛出指定异常:
1 | def error_handler(): |
close方法:在生成器暂停处抛出GeneratorExit异常:
1 | def cleanup_generator(): |
14.2.3 生成器的高级应用
无限序列:生成器天然适合表示无限序列:
1 | def fibonacci(): |
数据管道:生成器可以串联形成数据处理管道:
1 | def read_lines(filepath): |
递归生成器:生成器可以递归调用自身处理嵌套结构:
1 | def flatten(nested): |
14.3 生成器表达式
14.3.1 语法与性能
生成器表达式是列表推导式的惰性版本,使用圆括号而非方括号:
1 | import sys |
14.3.2 嵌套生成器表达式
1 | matrix = [ |
14.3.3 生成器表达式的局限
生成器表达式只能包含单个表达式,不能包含复杂语句。对于复杂逻辑,应使用生成器函数:
1 | # 生成器表达式:简单转换 |
14.4 yield from:子生成器委托
14.4.1 基本机制
yield from是Python 3.3引入的语法,用于将生成器的部分操作委托给子生成器。它不仅简化了嵌套生成器的写法,还建立了主生成器与子生成器之间的双向通信通道。
1 | def chain(*iterables): |
14.4.2 yield from的完整语义
yield from不仅仅是for item in subgen: yield item的语法糖,它还处理了以下细节:
- 将
send()的值传递给子生成器 - 将
throw()的异常传递给子生成器 - 当子生成器完成时,其
return值成为yield from表达式的值 - 正确处理
StopIteration
1 | def subgen(): |
双向通信示例:
1 | def echo_subgen(): |
14.4.3 yield from与归约模式
yield from的一个重要应用是归约(Reduction)模式——子生成器产生部分结果,主生成器汇总:
1 | def average_gen(): |
14.5 itertools模块详解
14.5.1 无限迭代器
1 | from itertools import count, cycle, repeat |
14.5.2 终止迭代器
1 | from itertools import ( |
14.5.3 组合迭代器
1 | from itertools import combinations, combinations_with_replacement, permutations, product |
14.5.4 构建数据处理管道
1 | from itertools import islice, chain, groupby |
14.6 自定义迭代器设计模式
14.6.1 惰性求值迭代器
1 | class LazyRange: |
14.6.2 缓冲迭代器
1 | class BufferedIterator: |
14.6.3 分块迭代器
1 | def chunked(iterable, size): |
14.6.4 合并迭代器
1 | def merge_sorted(*iterables, key=None): |
14.7 生成器与内存优化
14.7.1 大文件处理
1 | def read_large_file(filepath, chunk_size=8192): |
14.7.2 流式数据处理
1 | def stream_processor(data_stream): |
14.7.3 生成器与递归的对比
1 | import sys |
14.8 前沿技术动态
14.8.1 生成器与异步编程
生成器是Python异步编程(async/await)的基础。在Python 3.5之前,协程就是基于生成器实现的:
1 | import types |
14.8.2 生成器与结构化并发
Python 3.11+引入了TaskGroup,结合生成器可以构建更安全的并发模式:
1 | import asyncio |
14.8.3 生成器在数据科学中的应用
1 | def batch_generator(data, batch_size, shuffle=False): |
14.9 本章小结
本章深入探讨了Python生成器与迭代器机制:
- 迭代协议:可迭代协议与迭代器协议的区分、
for循环的底层机制、分离可迭代对象与迭代器的最佳实践 - 生成器函数:
yield的执行模型、生成器状态机、send/throw/close的协程式通信 - 生成器表达式:惰性求值的内存优势、嵌套表达式、与列表推导式的对比
- yield from:子生成器委托机制、双向通信、归约模式
- itertools:无限迭代器、终止迭代器、组合迭代器、数据处理管道
- 自定义迭代器:惰性求值、缓冲、分块、合并等设计模式
- 内存优化:大文件处理、流式数据处理、生成器与递归的对比
14.10 习题与项目练习
基础习题
迭代器实现:实现一个
PermutationIterator类,给定一个序列,按字典序逐个返回所有排列。生成器管道:使用生成器实现一个CSV文件处理管道,支持过滤、映射、聚合操作,且全程惰性求值。
素数筛:使用生成器实现埃拉托斯特尼筛法(Sieve of Eratosthenes),生成无限素数序列。
进阶习题
协程式生成器:实现一个基于
send的词频统计生成器,支持动态添加文本、查询词频、重置统计。合并K路有序流:实现
merge_k_sorted(k_streams),合并K个已排序的生成器为一个有序生成器,要求空间复杂度为O(K)。迭代器适配器:实现一组迭代器适配器:
peekable(可预览)、partition(分流)、roundrobin(轮流取值)。
项目练习
日志分析引擎:使用生成器管道实现一个日志分析系统,支持:
- 惰性读取大日志文件
- 多条件过滤(时间范围、级别、关键词)
- 实时统计(QPS、错误率、响应时间分布)
- 结果导出(JSON/CSV)
- 支持管道组合与复用
数据流处理框架:设计一个基于生成器的数据流处理框架,包括:
- Source:数据源抽象(文件、网络、数据库)
- Transform:数据转换算子(map、filter、flatmap、window)
- Sink:数据输出(文件、数据库、控制台)
- 支持背压(Backpressure)机制
- 支持检查点(Checkpoint)与故障恢复
14.11 延伸阅读
14.11.1 迭代器与生成器理论
- PEP 234 — Iterators (https://peps.python.org/pep-0234/) — 迭代器协议设计
- PEP 255 — Simple Generators (https://peps.python.org/pep-0255/) — 生成器语法设计
- PEP 380 — Syntax for Delegating to a Subgenerator (https://peps.python.org/pep-0380/) — yield from语法
- 《Fluent Python》第14-17章 — 迭代器、生成器与协程深度解析
14.11.2 itertools与函数式编程
- itertools官方文档 (https://docs.python.org/3/library/itertools.html) — 迭代器工具详解
- more-itertools库 (https://more-itertools.readthedocs.io/) — 扩展迭代器工具
- 《Functional Programming in Python》 (David Beazley) — 函数式编程实践
14.11.3 协程与异步编程
- PEP 492 — Coroutines with async and await syntax (https://peps.python.org/pep-0492/) — 异步语法设计
- 《Python Concurrency with asyncio》 (Matthew Fowler) — 异步编程实战
- asyncio官方文档 (https://docs.python.org/3/library/asyncio.html) — 异步IO框架
14.11.4 数据处理实践
- Generator Tricks for Systems Programmers (David Beazley) — 生成器高级技巧
- Pandas迭代器文档 (https://pandas.pydata.org/docs/user_guide/io.html) — 大数据处理
- Dask数据流 (https://docs.dask.org/) — 并行计算框架
下一章:第15章 异常处理



