Python · 2 分钟阅读
`zip()` 函数
目录
zip() 把 多个可迭代对象按位置配对,产出“每一列”的元组。配合
* 解包运算符,还能把配对好的结果再“拆回”原始形状。
1. 基本用法
a = [1, 2, 3]
b = ["a", "b", "c"]
print(list(zip(a, b)))
# [(1, 'a'), (2, 'b'), (3, 'c')]
要点:
- 返回迭代器,需要
list()/tuple()才能看到全部。 - 按最短截断:长度不一时,短的到头就停。
- 支持 任意数量 的可迭代对象:
zip(a, b, c, ...)。
2. zip(*iterables) 解读
strs = ["flower", "flow", "flight"]
print(list(zip(*strs)))
# [('f', 'f', 'f'), ('l', 'l', 'l'), ('o', 'o', 'i'), ('w', 'w', 'g')]
把 *strs 看成“把 strs 解包为独立参数”:
zip(*strs) ≡ zip("flower", "flow", "flight")
zip 再“把每个串同位置的字符放成一组”:
zip 的结果 = [第 0 列, 第 1 列, 第 2 列, ...]
= [(f,f,f), (l,l,l), (o,o,i), (w,w,g), ...]
这正是 最长公共前缀 这类题目的关键技巧:把列凑齐,按列做集合去重或
all/any判定。
3. 经典场景
3.1 同时遍历多个列表
names = ["Alice", "Bob", "Carol"]
ages = [30, 25, 28]
for name, age in zip(names, ages):
print(name, age)
3.2 构造字典
keys = ["name", "age", "city"]
vals = ["Alice", 30, "NY"]
print(dict(zip(keys, vals)))
# {"name": "Alice", "age": 30, "city": "NY"}
3.3 转置矩阵
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = list(zip(*matrix))
# [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
3.4 同时迭代多份数据
list1 = [1, 2, 3]
list2 = [10, 20, 30]
list3 = [100, 200, 300]
for a, b, c in zip(list1, list2, list3):
print(a + b + c)
3.5 用 itertools.zip_longest 处理不等长
import itertools
a = [1, 2, 3, 4]
b = ["x", "y"]
print(list(itertools.zip_longest(a, b, fillvalue=0)))
# [(1, 'x'), (2, 'y'), (3, 0), (4, 0)]
4. zip 的反向操作:解包
pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
nums, letters = zip(*pairs)
print(nums) # (1, 2, 3)
print(letters) # ('a', 'b', 'c')
这正是“转置”的反向操作。
5. 易错点
- 用
list(zip(xs, ys))而不是zip(xs, ys)当场消费,否则迭代器一次
用完就空。 - 长度不一时会被截断。不想被截断就用
itertools.zip_longest。 - 不要拿
zip当dict.update的替身:它产出的是元组而不是“已合并”
的结果。 - 不是递归——
zip不会自动把内部可迭代对象再展开(用itertools.chain
或zip(*...))。
6. 小结
zip(*iterables)按位置配对,返回迭代器,按 最短 截断。*是解包,让你能 转置 数据或给zip喂“展开后的多个序列”。- 长度不一致时用
itertools.zip_longest(fillvalue=...)。 zip在“同时遍历 / 转置 / 构造 dict / 按列判定”场景里几乎无处不在。