查看全课大纲(第 47 / 51 节)
- 1.Python 是什么?为什么值得学?
- 2.如何为 Python 编程准备一个“全家桶”环境?
- 3.Python 有哪几种执行方法?
- 4.行与缩进到底有什么用?
- 5.注释有什么用,怎么写?
- 6.变量:如何给数据起个好名字?
- 7.运算符的优先级和常见坑点是什么?
- 8.Python 中,数字和布尔值究竟有哪几种?
- 9.输入函数 `input()` 和文件读取 `open()` 怎么用?
- 10.如何将程序的结果展示给用户或保存下来?
- 11.CSV 文件怎么读怎么写才方便?
- 12.列表是什么,如何创建和访问它?
- 13.列表的修改操作,有哪些方法?
- 14.列表切片为什么能取到部分元素?排序和查找又该怎么用?
- 15.判断语句:如何让程序根据条件做不同的事?
- 16.for 循环如何遍历序列中的元素?
- 17.while 循环什么时候才会停?
- 18.while 循环的结束条件,你写对了吗?
- 19.循环中途想提前结束,怎么办?
- 20.`break` 和 `continue` 到底有什么区别?
- 21.列表推导式如何让代码更简洁高效?
- 22.字符串怎么定义、拼接和操作?
- 23.元组:为什么定义单个元素时要加逗号?
- 24.集合(set)怎么用?如何快速去重和做集合运算?
- 25.字典是什么,为什么比列表更方便?
- 26.字典的增删改查与遍历,如何避免 KeyError?
- 27.函数里的变量,为什么有的能用有的不能用?
- 28.在函数内部修改全局变量,为什么有时不生效?
- 29.函数里能修改全局变量吗?返回值怎么用?
- 30.匿名函数:如何用 lambda 快速定义简单函数?
- 31.面向对象编程是什么,为什么需要它?
- 32.类中的方法和属性到底怎么定义和使用?
- 33.如何控制对对象内部属性和方法的访问?
- 34.异常发生时,程序会怎样继续执行?
- 35.如何组织代码:包和模块
- 36.`if __name__ == '__main__'` 到底有什么用?
- 37.如何用 IDE 的 Debug 功能排查程序错误?
- 38.Matplotlib 绘图的第一步该做什么?
- 39.Figure 是什么,如何设置图形尺寸?
- 40.如何自定义 Matplotlib 的坐标轴?
- 41.如何为图表添加图例,让不同曲线一目了然?
- 42.饼图怎么画才能直观展示数据占比?
- 43.如何用 Matplotlib 绘制散点图?
- 44.柱状图怎么画?
- 45.如何使用 Matplotlib 绘制等高线图?
- 46.如何在 Matplotlib 中绘制子图?
- 47.zip 函数如何把多个列表“打包”在一起?
- 48.如何给可迭代对象加上索引?
- 49.random 模块如何生成随机数?
- 50.math 模块怎么用?
- 51.Counter 如何快速统计元素出现次数?
zip 函数如何把多个列表“打包”在一起?
约 7 分钟
小象实战讲义 · Python 编程从入门到实践
在编程中,我们常常需要把多个列表(或其他可迭代对象)中相同位置的元素关联起来,比如把姓名列表与成绩列表一一对应。zip 函数就是为这类需求而生的“打包”工具。本节是第 6 章《一些常用的函数》的第 1 节,你将学会如何合并数据、如何反向“解压”,以及遇到长度不一致时结果会怎样。
💡 核心导读
- 作用:把多个可迭代对象中对应位置的元素打包成一个个元组。
- 语法:
zip(iterable1, iterable2, ...),返回一个zip对象。 - 版本差异:Python 2 返回元组列表,Python 3 返回
zip对象,需要转换才能查看内容。 - 长度处理:传入的对象长度不一致时,结果长度由最短的那个决定。
- 反向操作:
zip(*zipped)可以把打包结果解压回原来的多列。
zip 函数是什么?
zip 是 Python 的内置函数,作用是把多个可遍历的数据对象(列表、元组、字符串等)中对应位置的元素组合到一起。它的调用格式很简单:
zip(iterable1, iterable2, ...)注意版本差异:在 Python 2 中,zip 直接返回由元组组成的列表;在 Python 3 中,它返回一个 zip 对象。本节所有示例都按 Python 3 讲解,所以打印之前通常要先做一次类型转换。
怎么用 zip 打包数据?
基本打包与结果查看
假设我们有两个列表,分别存储学号和姓名,希望把它们一一对应起来。
# 定义两个列表
ids = [1001, 1002, 1003]
names = ['小明', '小红', '小刚']
# 打包:把两个列表中对应位置的元素配成元组
zipped = zip(ids, names)
# Python 3 中 zip 返回的是 zip 对象,不是列表
print(type(zipped))
# 转成列表才能看到打包后的内容
print(list(zipped))
# 长度不一致时:结果只保留到最短的那个列表
list_a = [1, 2, 3]
list_b = ['a', 'b', 'c', 'd', 'e'] # 比 list_a 长
print(list(zip(list_a, list_b)))<class 'zip'>
[(1001, '小明'), (1002, '小红'), (1003, '小刚')]
[(1, 'a'), (2, 'b'), (3, 'c')]zip(ids, names) 把 1001 和 '小明'、1002 和 '小红'、1003 和 '小刚' 分别配成元组。zip 对象本身不直接显示内容,所以示例里用 list() 转换了一次。
长度不一致时以最短为准
如果两个列表长度不同,zip 不会报错,也不会补齐,而是以最短的那个为准,较长列表多出来的元素会被忽略。上面的代码块最后一行就是这种情况:list_b 有两个多余元素,但结果只到 list_a 的长度。
如果业务上要求两边长度必须对齐,应在调用 zip 之前自己先把数据补齐,而不是指望 zip 自动处理。
转换成字典或集合
zip 的结果可以直接交给 dict(),快速建立映射关系:每个元组的第一个元素成为键,第二个元素成为值。
keys = ['name', 'age', 'city']
values = ['李雷', 18, '北京']
# 转成字典:元组的第一个元素作键,第二个元素作值
print(dict(zip(keys, values)))
# 也可以转成集合;集合无序,打印前先 sorted 保证输出稳定
print(sorted(set(zip(keys, values)))){'name': '李雷', 'age': 18, 'city': '北京'}
[('age', 18), ('city', '北京'), ('name', '李雷')]除了列表和字典,转成集合同样可行。集合只保留打包后的元组,并会自动去重,因此打印时先排序,才能得到稳定、可对照的结果。
解压:zip(*zipped)
有打包就有解压。做法仍然是调用 zip,只是在传入参数前加一个星号 *,把列表“摊开”成多个参数。
# 一个已经打包好的列表
paired_data = [('苹果', 5), ('香蕉', 3), ('橘子', 8)]
# 前面的 * 把列表摊开成三个参数,再交给 zip 重新组合
unzipped = zip(*paired_data)
print(list(unzipped))[('苹果', '香蕉', '橘子'), (5, 3, 8)]解压后得到两个元组:第一个是所有水果名,第二个是所有数量,正好恢复了原来的“列”结构。需要注意,解压返回的同样是 zip 对象,所以也要转换后才能查看。
典型场景:同时遍历多个序列
zip 最常见的用途是在 for 循环里同时取出多个序列中对应位置的元素,省掉手动维护下标。
# 名字和体重一一对应
names = ['Tom', 'Jerry', 'Dora']
weights = [15, 5, 30]
for name, weight in zip(names, weights):
print('{} 的重量是 {} 公斤'.format(name, weight))Tom 的重量是 15 公斤
Jerry 的重量是 5 公斤
Dora 的重量是 30 公斤循环每一轮,zip 提供一个 (名字, 体重) 元组,再用两个循环变量分别接住,代码比按下标访问清晰得多。
📝 动手练一练
- 有两个列表
fruits = ['apple', 'banana', 'cherry']和prices = [5, 3, 7],请用zip把它们组合成字典。再对a = [10, 20, 30, 40]、b = [1, 2]、c = [100, 200, 300]执行zip(a, b, c),转成列表后结果是什么?为什么?
👉 点击查看参考答案
思路:组合字典直接用 dict(zip(...));三个列表长度不同,结果长度由最短的 b(长度 2)决定。
fruits = ['apple', 'banana', 'cherry']
prices = [5, 3, 7]
print(dict(zip(fruits, prices)))
a = [10, 20, 30, 40]
b = [1, 2]
c = [100, 200, 300]
print(list(zip(a, b, c))){'apple': 5, 'banana': 3, 'cherry': 7}
[(10, 1, 100), (20, 2, 200)]常见错误
| 错误写法 | 现象或报错 | 原因 | 正确写法 |
|---|---|---|---|
print(zip(a, b)) | 输出类似 <zip object at 0x...> | Python 3 的 zip 返回对象,不直接显示内容 | print(list(zip(a, b))) |
| 以为结果长度与最长输入一致 | 长列表尾部数据被丢弃,程序逻辑出错 | zip 以最短的输入为准 | 调用前先把数据补齐,或只传等长序列 |
对同一个 zip 对象遍历两次 | 第二次遍历得不到任何内容 | zip 对象是迭代器,遍历一次后元素就被消费完 | 需要多次使用先转成列表:pairs = list(zip(a, b)) |
旧写法对照
下表列出旧教程中可能见到的写法与 Python 3 的对应写法,按现代 Python 3 学习即可:
| Python 2 旧写法 | Python 3 正确写法 | 说明 |
|---|---|---|
zip(a, b) 直接得到元组列表 | list(zip(a, b)) | Python 3 中返回 zip 对象,需转换才能查看 |
小结
zip(iterable1, iterable2, ...)把多个可迭代对象中对应位置的元素打包成元组。- Python 3 中返回
zip对象,查看内容前要转成list、dict、set等类型。 - 输入长度不一致时,结果以最短的那个为准,多余元素被忽略。
zip(*zipped)是解压操作,能把打包结果还原成原来的多列。zip常用于在for循环中同时遍历多个相关序列。
📋 行动清单
- 把示例中的
ids、names改成三个列表,用zip打包后转成列表查看结果。 - 对打包结果执行
zip(*...)解压,观察是否恢复了原始数据。 - 故意让两个列表长度不同,确认输出只保留到最短列表的长度。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载第6章代码包:zip(含1 个 Notebook)ZIP · 636B