python 的 zip 函数是惰性、短路的并行迭代器,按位置配对各序列元素生成元组,任一序列耗尽即终止,不创建新列表、不修改原序列,也不要求等长。

Python 的 zip 函数不是“合并”多个序列,而是按位置配对、逐个取值的并行迭代器。它不创建新列表(除非显式转为 list),也不修改原序列,核心是“同步拉链式取值”——每次从每个可迭代对象中各取一个元素,组成元组,直到任意一个耗尽为止。
zip 的底层逻辑:惰性生成 + 短路终止
zip 返回的是一个迭代器(Python 3),内部维护多个迭代器的状态。每次调用 __next__() 时,它会:
- 依次对每个传入的可迭代对象调用
next() - 将所有成功取出的元素打包成一个元组
- 一旦任一对象抛出
StopIteration,立即停止,不再继续取其他对象的后续元素
例如:zip([1,2,3], ['a','b']) 只产生 (1,'a'), (2,'b'),第三个元素 3 被忽略——这不是“截断”,而是“自然终止”。
并行遍历的本质:位置对齐,非长度对齐
zip 不要求输入序列等长,它只保证“第 i 次迭代拿到的是所有序列的第 i 个元素”。这意味着:
立即学习“Python免费学习笔记(深入)”;
- 可用于安全地同时遍历多个相关数据源(如字段名与字段值)
- 若需补全缺失值,应使用
itertools.zip_longest(),而非自行 padding - 空序列会导致 zip 立即结束,结果为空迭代器
常见误区与等效手写实现
有人误以为 zip 是“先转列表再配对”,其实它完全避免中间存储。以下代码模拟其核心行为(简化版):
def my_zip(*iterables):
iterators = [iter(it) for it in iterables]
while True:
try:
yield tuple(next(it) for it in iterators)
except StopIteration:
return
注意:这个实现和内置 zip 一样,遇到第一个 StopIteration 就退出,不会尝试继续读其他迭代器。
实际应用中的关键细节
- 单个参数传入 zip(如
zip(seq))会返回单元素元组的迭代器,常用于“解包还原”场景 - 配合星号解包可逆向操作:
list(zip(*zip(a,b))) == list(zip(a,b))成立,但仅当 a、b 等长时才完全等价 - zip 对生成器、文件对象等一次性迭代器也有效,但只能遍历一次










