
平时咱们用 Python 处理数据的时候,经常会碰到一些重复又繁琐的操作,比如分批处理大文件、合并不同长度的列表、生成参数组合等等。这时候 Python 自带的 itertools 模块就派上大用场了,里面藏着不少好用的函数,能帮咱们把代码写得又快又漂亮。今天就给大家扒一扒 5 个特别实用的 "宝藏函数",每个都带简单好懂的案例,保证代码能直接跑起来!
这个函数是 Python 3.12 之后新增的,专门用来处理大规模数据。啥意思呢?比如你有 10 万个数据,要是一股脑全塞进内存里,电脑可能直接卡住。batched 能让你自己定一个批次大小,比如每 100 个数据处理一次,每次只在内存里存这 100 个,处理完一批再取下一批,就像吃自助餐一样,分批次拿食物,不把胃撑坏。特别适合处理数据流、大文件读取这种场景。
比如咱们生成 1 到 10 这 10 个数,想每 3 个分一批处理:
from itertools import batched
numbers = range(1, 11)
for batch in batched(numbers, 3):
print(list(batch))运行结果:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[10] # 最后一批不够3个,就剩10自己要是处理更大的数据,比如模拟一个无限数据流(当然实际会加停止条件),每次处理 100 个,也不会占太多内存。比如从文件里逐行读取,每 100 行处理一次,写法差不多,把 range 换成文件读取的迭代器就行。
普通的 zip 函数大家都用过,比如 zip (1,2,a,b,c),结果只会到短的那个列表结束,也就是 (1,'a'),(2,'b'),第三个 'c' 就被扔掉了。但现实中经常遇到两个列表长度不一样的情况,比如统计两个部门的员工绩效,一个部门 5 人,一个部门 3 人,想把每个人的绩效一一对应,短的部门没数据的地方就需要补个默认值,比如补个 0 或者 ' 无'。zip_longest 就支持自定义填充值,让长的列表也能对齐,不会漏掉任何一个数据。
输入列表 1 | 输入列表 2 | 普通 zip 结果 | zip_longest (填充 None) | zip_longest (填充 '-') |
|---|---|---|---|---|
1, 2 | 'a', 'b', 'c' | (1, 'a'), (2, 'b') | (1, 'a'), (2, 'b'), (None, 'c') | (1, 'a'), (2, 'b'), ('-', 'c') |
具体代码:
from itertools import zip_longest
list1 = [1, 2]
list2 = ['a', 'b', 'c']
# 普通zip
print("普通zip结果:", list(zip(list1, list2)))
# zip_longest默认填充None
print("zip_longest填充None:", list(zip_longest(list1, list2)))
# 自定义填充'-'
print("zip_longest填充'-':", list(zip_longest(list1, list2, fillvalue='-')))运行结果:
普通zip结果: [(1, 'a'), (2, 'b')]
zip_longest填充None: [(1, 'a'), (2, 'b'), (None, 'c')]
zip_longest填充'-': [(1, 'a'), (2, 'b'), ('-', 'c')]比如你想生成颜色和尺寸的所有组合,颜色有 ' 红 ',' 蓝 ',尺寸有 'S','M','L',正常得写两层循环,外层颜色,内层尺寸,然后把每个组合存起来。但 product 能直接帮你生成笛卡尔积,也就是所有可能的组合,一行代码搞定,再也不用写一堆 for 循环嵌套了。特别适合枚举参数组合、生成测试用例、配置项排列等场景。
生成颜色和尺寸的所有组合:
from itertools import product
colors = ['红', '蓝']
sizes = ['S', 'M', 'L']
for combo in product(colors, sizes):
print(combo)运行结果:
('红', 'S')
('红', 'M')
('红', 'L')
('蓝', 'S')
('蓝', 'M')
('蓝', 'L')如果是三个列表的组合,比如再加一个材质 ' 棉 ',' 麻 ',也是一样的写法,product (colors, sizes, materials),会生成三层组合,代码依然简洁。
普通的 map 函数只能处理单参数的函数,比如 map (lambda x: x*2, 1,2,3)。但如果你的函数需要两个参数,比如计算 x 的 y 次方,函数是 pow (x,y),而你的数据是一个列表 of 元组,比如 (2,3),(3,2),(4,2),这时候普通 map 就不行了,因为它传进去的是整个元组,比如第一个参数是 (2,3),而 pow 需要两个参数。这时候 starmap 就派上用场了,它会自动把元组解包成单个参数,也就是把 (2,3) 拆成 2 和 3 传给 pow,这样就能正确计算了。
普通 map 报错写法 vs starmap 正确写法:
from itertools import starmap
# 普通map会报错,因为传的是元组,pow需要两个参数
# print(list(map(pow, [(2,3),(3,2),(4,2)]))) # 会报错:TypeError: pow expected 2 arguments, got 1
# starmap正确写法
print(list(starmap(pow, [(2,3),(3,2),(4,2)])))运行结果:
[8, 9, 16]再举个例子,计算多个点到原点的距离,点坐标是 (x,y),函数是计算√(x²+y²),用 starmap:
import math
points = [(3,4), (0,0), (6,8)]
distances = list(starmap(lambda x,y: math.sqrt(x**2 + y**2), points))
print(distances)运行结果:
[5.0, 0.0, 10.0]groupby 可以把数据按照某个键分组,比如按字符串长度分组,按年龄分段分组,按日志中的错误类型分组等等。不过要注意,它要求数据是按照分组键排好序的,因为它是按照连续相同的键来分组的。比如先把列表按长度排序,然后相同长度的就会连续出现,groupby 就能把它们分到一组。每组会有一个键(比如长度 5),和对应的迭代器,里面是所有该键的数据。
按字符串长度分组:
from itertools import groupby
from operator import itemgetter # 辅助排序的工具
# 先定义数据,然后按长度排序
words = ['apple', 'banana', 'cat', 'dog', 'elephant', 'fish']
# 按长度排序,这样相同长度的会连续
words_sorted = sorted(words, key=len)
# 分组
for length, group in groupby(words_sorted, key=len):
print(f"长度为{length}的单词:{list(group)}")运行结果:
长度为3的单词:['cat', 'dog', 'fish']
长度为5的单词:['apple']
长度为6的单词:['banana']
长度为8的单词:['elephant']这里 key 参数可以是一个函数,比如 len,也可以是自定义的函数,比如按首字母分组,就需要先按首字母排序,然后 key=lambda x: x 0。
再举个按数值范围分组的例子,比如学生成绩按分数段(60 以下,60-80,80 以上)分组:
scores = [75, 88, 55, 90, 62, 70, 45]
# 先排序,然后定义分组函数
scores_sorted = sorted(scores)
def get_group(score):
if score < 60:
return '不及格'
elif score < 80:
return '中等'
else:
return '优秀'
for group, items in groupby(scores_sorted, key=get_group):
print(f"{group}:{list(items)}")运行结果:
不及格:[45, 55]
中等:[62, 70, 75]
优秀:[88, 90]总结:5 个函数各显神通,按需选择效率高
函数名 | 核心功能 | 必备条件 / 注意点 | 典型场景 |
|---|---|---|---|
batched | 分批处理数据,控制内存占用 | Python 3.12 + 版本 | 大文件处理、数据流解析 |
zip_longest | 对齐不同长度列表,支持填充缺失值 | 需导入 itertools | 合并长短不一的配置数据 |
product | 生成所有组合,笛卡尔积 | 简单参数枚举 | 配置项组合、测试用例生成 |
starmap | 处理多参数函数,自动解包元组 | 数据以元组形式存储 | 多参数函数批量应用 |
groupby | 按键分组数据,需先排序 | 数据需按分组键排序 | 日志分组、数据归类 |
这几个函数都是 itertools 里的 "精兵强将",学会之后能省掉很多重复代码,尤其是处理大规模数据或者复杂组合时,优势特别明显。建议大家把代码案例自己敲一遍,试试不同的参数,感受一下它们的灵活性。下次遇到类似的数据处理问题,就能第一时间想到合适的工具,再也不用对着代码发愁啦!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。