R / Richie全部文章 ↑

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 / 按列判定”场景里几乎无处不在。