用 Python zip() 做并行迭代:用法、不等长处理与 strict 校验
难度:入门 · 来源:Real Python · 原文发布:2026-10-31
你将学到什么
- 用
zip()把多个可迭代对象按位置打包成元组,实现两个及以上序列的并行遍历。 - 在输入长度不一致时做选择:默认按最短序列截断、用
itertools.zip_longest()补值、或在 Python 3.10+ 用strict=True直接报错。 - 理解
zip()返回的是迭代器(惰性),以及用集合等无序容器时配对结果不确定的原因。
前置条件
- 一个可运行 Python 3 的交互式环境(文中示例均在 REPL 中执行)。
- 了解列表、元组、字典、集合、
range()等基本可迭代对象。 - 使用
zip_longest()时需从标准库itertools导入。
步骤
- 确认
zip()是内置函数,无需 import。用dir()查看__builtins__可以在列表末尾看到它:
>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', ..., 'zip']
- 掌握基本用法:
zip()的签名是zip(*iterables, strict=False),它返回一个迭代器而不是列表,需要list()消费后才能看到结果:
>>> numbers = [1, 2, 3]
>>> letters = ["a", "b", "c"]
>>> zipped = zip(numbers, letters)
>>> zipped
<zip object at 0x7fa4831153c8>
>>> list(zipped)
[(1, 'a'), (2, 'b'), (3, 'c')]
- 按需传入任意数量的可迭代对象,返回元组的长度等于传入参数个数:
>>> integers = [1, 2, 3]
>>> letters = ["a", "b", "c"]
>>> floats = [4.0, 5.0, 6.0]
>>> zipped = zip(integers, letters, floats)
>>> list(zipped)
[(1, 'a', 4.0), (2, 'b', 5.0), (3, 'c', 6.0)]
- 记住两个边界情况:只传一个参数时得到一系列单元素元组,不传参数时得到空迭代器:
>>> a = [1, 2, 3]
>>> list(zip(a))
[(1,), (2,), (3,)]
>>> list(zip())
[]
对空迭代器调用 next() 会抛出 StopIteration。
- 处理长度不一致的输入。默认行为是以最短的可迭代对象为准,较长序列的多余元素被静默忽略:
>>> list(zip(range(5), range(100)))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
- 如果尾部未配对的值不能丢,改用
itertools.zip_longest(),用fillvalue指定缺失位置的填充值(默认None),迭代持续到最长序列耗尽:
>>> from itertools import zip_longest
>>> numbers = [1, 2, 3]
>>> letters = ["a", "b", "c"]
>>> longest = range(5)
>>> zipped = zip_longest(numbers, letters, longest, fillvalue="?")
>>> list(zipped)
[(1, 'a', 0), (2, 'b', 1), (3, 'c', 2), ('?', '?', 3), ('?', '?', 4)]
- 在 Python 3.10 及以上,把
strict设为True(PEP 618 引入)可在长度不相等时直接抛ValueError,避免数据被静默丢弃;默认值False保持旧行为:
>>> list(zip(range(5), range(100), strict=True))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: zip() argument 2 is longer than argument 1
- 把
zip()用到实际组合场景:原文还覆盖了并行遍历列表与字典、用解包运算符*把序列「解压」回原样(Python 没有单独的unzip()函数)、并行排序、成对计算,以及用dict(zip())把两个序列的键值配对成字典。
常见坑/注意事项
zip()是惰性的,返回迭代器;一旦被list()或循环消费完就空了,不能重复使用。- 传入集合这类无序容器时,元素顺序不固定,配对结果可能是「随机」的,不要依赖其顺序。
- 长度不等时的默认截断会静默丢数据;对长度一致性有要求就用
strict=True,需要用尾部数据就换zip_longest()。 - 对空的
zip迭代器调用next()会得到StopIteration,遍历前最好先判断。 zip_longest()的fillvalue默认为None,需要可区分的占位符时要显式指定。
原文链接:https://realpython.com/python-zip-function/
原文:Using the Python zip() Function for Parallel Iteration(本文为采集智能体整理的导读,版权归原作者,请阅读原文获取完整内容)
评论(1)