查看: 497|回复: 3

Python里zip()并行遍历多个序列的实用技巧与实战案例

[复制链接]
发表于 前天 09:00 | 显示全部楼层 |阅读模式
在Python开发中,经常需要把多个列表按索引一一对应地处理,比如学生姓名、年龄、邮箱分别存储在不同列表,然后输出每个人的完整信息。传统的range(len())写法虽然可行,但不够Pythonic。zip()函数能够将多个可迭代对象的对应元素打包成元组,从而实现优雅的并行遍历。本文从基础用法到高级技巧,配合实战案例,帮你彻底掌握zip()。
  1. names = ["张三", "李四", "王五"]
  2. ages = [25, 30, 28]
  3. emails = ["zs@test.com", "ls@test.com", "ww@test.com"]
  4. # 传统写法(不推荐)
  5. for i in range(len(names)):
  6.     print(f"{names[i]}, {ages[i]}岁, {emails[i]}")
  7. # 使用zip(推荐)
  8. for name, age, email in zip(names, ages, emails):
  9.     print(f"{name}, {age}岁, {email}")
复制代码

一、zip()的基本用法
zip(*iterables)将多个可迭代对象的对应元素打包成元组,返回一个迭代器。如果传入的序列长度不一致,zip默认按最短的截断,多余元素被丢弃。如果希望按最长处理并填充缺失值,可以使用itertools.zip_longest,并指定fillvalue参数。
  1. from itertools import zip_longest
  2. short = [1, 2]
  3. long_list = [1, 2, 3, 4, 5]
  4. print(list(zip(short, long_list)))  # [(1, 1), (2, 2)]  截断
  5. print(list(zip_longest(short, long_list, fillvalue=0)))  # [(1,1),(2,2),(0,3),(0,4),(0,5)]
复制代码
如果需要严格检查长度一致性,Python 3.10+提供了strict参数:zip(a, b, strict=True)会在长度不匹配时抛出ValueError。也可以手动实现一个strict_zip函数来兼容旧版本。
zip对象是迭代器,只能遍历一次。需要多次使用时应先转换为列表。

二、经典应用
1. 并行遍历:同时处理多列数据,如学生各科成绩和姓名。
  1. students = ["张三", "李四", "王五"]
  2. math = [85, 92, 78]
  3. eng = [88, 86, 95]
  4. for name, m, e in zip(students, math, eng):
  5.     print(f"{name}: 数学{m}, 英语{e}")
复制代码
2. 构建字典:dict(zip(keys, values))快速从两个列表创建映射。
  1. keys = ["name", "age", "city"]
  2. values = ["张三", 25, "北京"]
  3. user = dict(zip(keys, values))
复制代码
3. 转置矩阵:zip(*matrix)将行转换为列。
  1. matrix = [[1,2,3],[4,5,6],[7,8,9]]
  2. transposed = list(zip(*matrix))
  3. print(transposed)  # [(1,4,7),(2,5,8),(3,6,9)]
复制代码
4. 成对处理:zip(data, data[1:])可以生成相邻元素对,用于计算移动平均或比较相邻变化。

三、zip与*解包的组合
zip(*pairs)可以把已经打包的元组列表“解压缩”回原始序列,称为unzip。例如将用户元组列表分离成姓名、年龄、城市三个元组。
  1. users = [("张三",25,"北京"),("李四",30,"上海")]
  2. names, ages, cities = zip(*users)
  3. print(names, ages, cities)
复制代码
行式数据与列式数据之间互相转换也很方便。

四、高级用法
1. 创建滑动窗口:zip(*(iterable[i:] for i in range(n)))可以实现大小为n的滑动窗口。
2. 多键排序:可以将排序键和原数据一起zip,然后排序后解包(装饰-排序-去装饰模式)。更常见的做法是直接用sorted的key参数。
3. 同时遍历多个字典:先确保键顺序一致,再用zip(dict1.values(), dict2.values())进行并行处理。

五、实战案例
1. 成绩合并计算器:ScoreMerger类接收姓名列表和各科成绩列表,利用zip构建成绩矩阵,计算总分、科目平均分和排名,并格式化输出报告。代码见原文章节6.1。
2. 配置文件对比工具:compare_configs函数接收两个配置字典,用zip遍历所有键,对比值的变化,输出新增、删除、修改的项。代码见原文章节6.2。

六、总结
zip()是Python中处理并行迭代的利器,核心要点:默认截断最短序列,返回迭代器,结合*解包可以实现行列转换,itertools.zip_longest处理不等长序列,Python 3.10+支持strict模式。遇到需要手写range(len())的场景,优先考虑zip()。
回复

使用道具 举报

发表于 前天 09:10 | 显示全部楼层

Re: Python里zip()并行遍历多个序列的实用技巧与实战案例

感谢分享!zip()确实是让代码更简洁、可读性更强的利器。之前我总习惯用range(len()),后来换成zip之后,不仅行数少了,逻辑也更清晰了。特别喜欢你提到的“转置矩阵”和“unzip”用法,这个在实际数据处理中非常实用。另外,关于strict参数,我之前在Python 3.10以下的环境里自己写过一个检查长度的辅助函数,现在有了内置支持就更方便了。想问下楼主,在多字典并行遍历的场景下,如果字典键顺序不一致,除了先排序还有别的推荐处理方式吗?
回复 支持 反对

使用道具 举报

发表于 前天 09:10 | 显示全部楼层

Re: Python里zip()并行遍历多个序列的实用技巧与实战案例

感谢楼主的分享!非常全面,从基础到进阶都讲得很清楚。zip 确实让代码简洁不少,特别是配合 * 解包做矩阵转置和构建字典,平时经常用到。我补充一个自己常用的场景:用 zip 结合 enumerate 同时获取索引和多个列表的元素,比如 `for i, (a, b) in enumerate(zip(list1, list2)):`,写起来也很清晰。另外 strict 参数在 3.10+ 确实是个好特性,之前总得手动检查长度。楼主的实战案例也很有启发,回头试试那个成绩合并计算器的设计。
回复 支持 反对

使用道具 举报

发表于 前天 09:10 | 显示全部楼层

Re: Python里zip()并行遍历多个序列的实用技巧与实战案例

写得非常全面,从基础到进阶都覆盖了。zip确实是日常处理多列表的利器,尤其转置矩阵和构建字典那两个用法我几乎每天都在用。之前一直没注意strict参数,看楼主提到3.10才支持,这个细节挺实用。想问下楼主,在实际项目中如果必须兼容旧版本,你一般是自己写个strict_zip函数还是用其他方式检查长度?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-15 04:07 , Processed in 0.033707 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部