itertools.chain 是合并多个可迭代对象的最优解,惰性求值、内存友好;chain.from_iterable 适用于嵌套结构;groupby 需预排序才能正确分组;islice 是安全截取迭代器的唯一方式。

用 itertools.chain 合并多个可迭代对象,别再写 for 循环拼接
当你要把几个列表、生成器或文件行流串成一个连续流时,itertools.chain 是最轻量也最符合 Python 语义的解法。它不立即展开数据,保持惰性求值,内存友好。
- 常见错误:用
+拼接列表(触发复制,且只支持 list)或手动for循环extend(破坏迭代器本质) - 正确写法:
chain(list_a, list_b, range(3), my_generator()),返回一个迭代器,可直接用于for或传给list() - 注意
chain.from_iterable的适用场景:当你有一堆嵌套的可迭代对象(如[[1,2], [3,4], (5,)]),它比chain(*nested)更安全(避免解包空序列报错)
itertools.groupby 必须先排序,否则分组结果不符合直觉
groupby 不是“按值归类”,而是“对连续相同键的元素分段”。如果输入没排好序,同一键的元素被分散,就会被拆成多组。
- 典型翻车现场:对未排序的
['a', 'b', 'a', 'c']用groupby(x),得到三组:('a', ['a'])、('b', ['b'])、('a', ['a'])—— 第二个'a'不会和第一个合并 - 正确做法:先用
sorted(data, key=key_func),再传给groupby;若原始顺序不能丢,可考虑用defaultdict(list)替代 - key 函数返回值必须可哈希;若需按对象属性分组,确保该属性稳定且可哈希(比如
lambda x: x.category)
用 itertools.islice 安全截取大迭代器,避开 list[10:20] 的陷阱
对生成器、文件对象或无限迭代器(如 count())做切片时,不能用方括号语法——那会触发 __getitem__,而多数迭代器不支持。必须用 islice。
-
islice(iterator, start, stop, step)返回新迭代器,不消耗原迭代器前面的项(除非start > 0,此时会跳过前start项) - 注意:不能反向切片(
stop 无效),也不能负索引;需要倒序取最后 N 项?得先转成deque(maxlen=N) - 常见误用:
islice(my_gen(), 1000000, 1000010)会跳过前一百万项——如果只是想取前 10 项,直接写islice(gen, 10)即可,别加多余参数
itertools.product 和 itertools.combinations_with_replacement 别混淆使用场景
这两个都生成组合,但语义完全不同,选错会导致逻辑错误或爆炸式增长。
立即学习“Python免费学习笔记(深入)”;
-
product(A, B)是笛卡尔积:所有(a,b)对,长度为len(A) * len(B);常用于参数网格搜索、路径枚举 -
combinations_with_replacement(iterable, r)是“可重复选 r 个的无序组合”:比如combinations_with_replacement('AB', 2)→('A','A'), ('A','B'), ('B','B');适合模拟抽样放回且不计顺序 - 容易踩坑:
permutations和combinations默认不放回;若要放回且有序,只能用product(比如密码暴力枚举:每个位置从字符集里独立选)
真正难的不是记住函数名,而是每次调用前确认:这个迭代器是否已耗尽?键是否已排序?切片范围是否超出生成能力?这些状态不会报错,只会静默返回空结果。









