进阶篇 · Advanced
lv.3 进阶
kp-038
itertools 与迭代工具箱
1. 一句话定义
itertools 是构建惰性迭代流水线的乐高积木:无穷生成、切片、分组、排列组合、链式拼接——全部以 C 实现、内存 O(1)、组合近乎无限。
2. 为什么重要
它被称为"最 Python 的模块":把 kp-012/013 的协议变成可组合的函数式工具。数据管道、批处理、去重分组等场景,itertools 一行顶十行循环。
3. 前置知识
4. 核心概念(五组积木)
python
from itertools import (count, cycle, islice, chain, groupby,
product, permutations, combinations,
accumulate, pairwise)
# ① 无穷生成器(必须配 islice/zip 限长)
count(10, 2) # 10, 12, 14, ... 无穷
cycle("AB") # A, B, A, B, ... 无穷
list(islice(count(), 5)) # [0, 1, 2, 3, 4]
# ② 拼接与切分
chain([1, 2], [3, 4]) # 1 2 3 4(惰性不复制)
list(pairwise([1, 2, 3, 4])) # [(1,2), (2,3), (3,4)]
# ③ 排列组合
list(combinations("ABC", 2)) # AB AC BC
list(product([0, 1], repeat=2)) # (0,0) (0,1) (1,0) (1,1)
# ④ 归约与累计
list(accumulate([1, 2, 3, 4])) # [1, 3, 6, 10](前缀和)
# ⑤ 分组(必须先按同 key 排序!)
rows = sorted(data, key=lambda r: r["dept"])
for dept, grp in groupby(rows, key=lambda r: r["dept"]):
print(dept, len(list(grp)))配套伙伴:functools(reduce、partial、lru_cache)、more_itertools(社区增强包:chunked、windowed 等)。
5. 原理与机制
text
流水线组合:每个 itertools 函数都返回新迭代器
islice(filter(None, chain(sources)), 1000)
= 建一条管道,数据流过时逐段加工,全程物化不超过 1000 条
与列表版差异:不构造任何中间列表(对比 kp-011 的生成器表达式)groupby 陷阱的根源:它只在相邻元素上分组——所以"按 key 分组"必须先按 key 排序(或用 more_itertools.groupby_unsorted)。
6. 关键事实(模型/图示)
text
选型:
有限集合 + 要结果列表 → 推导式(kp-011)
流式/无穷/超大集合 → itertools 管道
复杂聚合统计 → 让位 pandas/Polars(kp-041)7. 直观类比
itertools 像乐高基础件:count 是"永动传送带"、islice 是"截断刀"、groupby 是"分拣机"、chain 是"汇流器"。单件不起眼,但按需拼装就能搭出任意数据流水线——而列表推导式是"预制板",适合标准户型,流水线才适合异形工程。
8. 实例与案例
python
# 分批处理(chunked 的标准库写法)
def batches(it, n):
it = iter(it)
while batch := list(islice(it, n)):
yield batch
# 任意迭代器分页拉取 API
for page in batches(ids, 100):
call_api(page)9. 常见误区
- groupby 忘排序 —— 只对相邻分组,结果碎片化;先 sorted 再 groupby。
- 无限迭代器没有限长 ——
list(count())直接内存爆炸;无限积木必须配 islice/zip/break。 - itertools 结果二次消费 —— 全是迭代器,一次性(kp-012 老问题)。
- 为小列表硬上 itertools —— 三元素列表写
combinations不如显式循环清楚;工具服务可读性。
10. 自测题
list(islice(cycle("AB"), 5))输出什么?groupby分组错误的两个常见原因?batches函数为什么用while ... islice而不是for?
参考答案
['A', 'B', 'A', 'B', 'A']。- 未按分组键排序;源是已耗尽/共享的迭代器导致分块错乱。
- islice 取不足 n 个时 batch 短于 n,循环终止条件靠列表空判断——for 无法直接表达"每次取 n 个"的批次语义。
11. 与其他知识点的关系
12. 延伸阅读
- itertools 官方文档(每页末的 recipes 段落是宝藏)
- more-itertools 文档