Zip 函数
以下是一份 最全面、最清晰的 Python zip 函数知识整理,涵盖原理、用法、进阶技巧、陷阱、优化方案以及实战示例。
zip(*iterables)
作用:把多个可迭代对象“拉链式”配对,返回一个惰性的 zip 对象(迭代器)
示例:
a = [1, 2, 3]
b = ['a', 'b', 'c']
list(zip(a, b))
# [(1, 'a'), (2, 'b'), (3, 'c')]
zip() 本质上是 迭代器,不会一次性把数据装载到内存中。
z = zip(a, b)
next(z)
# (1, 'a')
a = [1, 2, 3]
b = ['x', 'y']
list(zip(a, b))
# [(1, 'x'), (2, 'y')]
只走到 最短的 iterable。
如果你需要补全,请用 itertools.zip_longest。
from itertools import zip_longest
list(zip_longest([1,2,3], ['a'], fillvalue=None))
输出:
[(1, 'a'), (2, None), (3, None)]
for x, y in zip(nums, names):
print(x, y)
keys = ['name', 'age', 'addr']
values = ['Tom', 20, 'HZ']
d = dict(zip(keys, values))
pairs = [(1, 'a'), (2, 'b'), (3, 'c')]
nums, letters = zip(*pairs)
# nums = (1, 2, 3)
# letters = ('a', 'b', 'c')
按照成绩排序学生和课程:
students = ["Alice", "Bob", "Cindy"]
scores = [90, 70, 85]
# 组合成 [(90, Alice), (70, Bob), ...]
sorted_students = [s for _, s in sorted(zip(scores, students))]
matrix = [
[1, 2, 3],
[4, 5, 6],
]
list(zip(*matrix))
# [(1,4), (2,5), (3,6)]
即把行 -> 列。
squares = (x*x for x in range(3))
cubes = (x**3 for x in range(3))
list(zip(squares, cubes))
zip 非常适合合并生成器。
for idx, (x, y) in enumerate(zip(a, b)):
print(idx, x, y)
users = [
{"name": "Tom", "age": 18},
{"name": "Lucy", "age": 20},
]
names, ages = zip(*[(u["name"], u["age"]) for u in users])
rows = zip(name_list, age_list, city_list)
for r in rows:
print(','.join(map(str, r)))
result = list(map(sum, zip([1,2,3], [4,5,6])))
# [5,7,9]
如果你要把列表每 N 个打包:
def chunk(iterable, n):
args = [iter(iterable)] * n
return zip(*args)
list(chunk([1,2,3,4,5,6], 3))
# [(1,2,3), (4,5,6)]
这是 zip 的高级技巧!
from functools import reduce
matrix = [
[1,2,3],
[4,5,6],
[7,8,9],
]
col_sum = [sum(col) for col in zip(*matrix)]
all(x == y for x, y in zip(a, b))
可以用在 tqdm 中:
for a, b in zip(data1, data2):
...
with open('data.csv','w') as f:
for row in zip(*columns):
f.write(','.join(map(str, row)) + '\n')
z = zip(a, b)
list(z)
list(z) # 第二次是空
务必注意。
如果你以为 zip 会补齐,那你应该用:
zip_longest
zip 的性能非常高:
- 无拷贝
- 惰性
- C 实现
- 内存极省
在你要“并行遍历多个序列”时优先使用 zip。
实际上 zip 的工作方式等价于:
def py_zip(*iterables):
iters = [iter(it) for it in iterables]
while True:
try:
yield tuple(next(it) for it in iters)
except StopIteration:
return
zip = 多序列并行迭代;以最短为准;惰性迭代器;可用于矩阵转置、生成 dict、解压、并行遍历。