问题的历史
zip() 函数作为一种方便的方式出现在 Python 中,用于将多个序列 "缝合" 成包含对应元素的元组,形成一种类似 "矩阵" 的结构。
问题
当开发者对不同长度的序列使用 zip 时,会出现错误,因为他们期望结果是最长的序列,或者在反向转换时错误地使用了解包。
解决方案
zip() 接受一个或多个序列,返回一个元组的迭代器,其中第 n 个元组包含所有序列的第 n 个元素。迭代在最短序列耗尽时结束。
代码示例:
names = ['John', 'Anna', 'Peter'] ages = [28, 22, 35] grouped = list(zip(names, ages)) print(grouped) # [('John', 28), ('Anna', 22), ('Peter', 35)]
关键特性:
如果将不同长度的序列传递给 zip,会发生什么?
结果将是最短序列的长度。其他元素将被忽略。
zip([1,2,3], ['a','b']) # [(1,'a'), (2,'b')]
可以 "展开" zip 吗?如何获取原始序列?
可以,通过星号解包和 zip(*iterator):
pairs = [(1, "a"), (2, "b")] numbers, letters = zip(*pairs) print(numbers) # (1, 2)
zip 和 itertools.zip_longest 有什么区别?
来自 itertools 的 zip_longest 会一直工作到最长的序列,并用指定的 fillvalue 填充缺失值。
from itertools import zip_longest zip_longest([1,2], ['a','b','c'], fillvalue=None) # [(1,'a'), (2,'b'), (None, 'c')]
我们通过 zip 处理用户和密码对,但列表长度不同。由于 zip 根据短列表工作,几个用户没有被考虑在内。
优点:
缺点:
为结合测试结果和学生姓名,我们使用 zip_longest 并设置 fillvalue="n/a",保留了所有参与者的数据。
优点:
缺点: