Python itertools 常用迭代组合技巧

10次阅读

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

Python itertools 常用迭代组合技巧

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.productitertools.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');适合模拟抽样放回且不计顺序
  • 容易踩坑:permutationscombinations 默认不放回;若要放回且有序,只能用 product(比如密码暴力枚举:每个位置从字符集里独立选)

真正难的不是记住函数名,而是每次调用前确认:这个迭代器是否已耗尽?键是否已排序?切片范围是否超出生成能力?这些状态不会报错,只会静默返回空结果。

text=ZqhQzanResources