itertools高级迭代器:cycle/count/accumulate/islice/tee
请详细介绍Python itertools模块中以下高阶函数的原理和使用场景:itertools.cycle、itertools.count、itertools.accumulate、itertools.islice、itertools.tee、itertools.zip_longest、itertools.pairwise。给出一个用itertools实现的滑动窗口平均值函数,以及用tee实现双向迭代的示例。处理无限迭代器时有哪些注意事项?
回答
屠龙少年
高级itertools函数:
import itertools
# cycle:无限重复
cycled = itertools.cycle(['A', 'B', 'C'])
[next(cycled) for _ in range(5)] # ['A','B','C','A','B']
# count:无限计数
itertools.count(start=10, step=2) # 10, 12, 14, ...
# accumulate:累加(可自定义函数)
itertools.accumulate([1, 2, 3, 4, 5]) # 1, 3, 6, 10, 15
itertools.accumulate([1, 2, 3, 4], max) # 1, 2, 3, 4(累计最大值)
# islice:切片迭代器(惰性)
itertools.islice(range(1000000), 10, 20) # 只生成10-19,不计算前面的
# tee:复制迭代器为多个(内存消耗随差异增大)
ite1, ite2 = itertools.tee([1,2,3,4,5], 2)
list(ite1) # [1,2,3,4,5]
list(ite2) # [1,2,3,4,5]
# zip_longest:短序列补默认值
itertools.zip_longest([1,2], [10,20,30], fillvalue=0) # (1,10),(2,20),(0,30)
# pairwise:连续配对(Python 3.10+)
itertools.pairwise([1,2,3,4]) # (1,2),(2,3),(3,4)
滑动窗口平均值:
def moving_average(iterable, n):
it = iter(iterable)
window = list(itertools.islice(it, n))
if len(window) == n:
yield sum(window) / n
for elem in it:
window.pop(0)
window.append(elem)
yield sum(window) / n
无限迭代器注意事项:
- 必须设退出条件(
itertools.islice或break) tee会缓存已消耗的元素,如果两个迭代器差异很大,内存消耗大cycle是无限循环,不要在list()中直接使用accumulate的initial参数(3.8+)可设置初始值