编程后端 Python 开发者

请解释一下 Python 中 zip() 函数的工作原理,它的用途是什么,以及在处理不同长度的序列时需要考虑哪些特性。

用 Hintsage AI 助手通过面试

回答。

问题的历史
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,会发生什么?

结果将是最短序列的长度。其他元素将被忽略。

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 会立即返回空。
  • 在 Python 3 中使用 zip 而没有转换为列表:zip 是一个迭代器,遍历后可能会被耗尽。

生活中的例子

负面案例

我们通过 zip 处理用户和密码对,但列表长度不同。由于 zip 根据短列表工作,几个用户没有被考虑在内。

优点:

  • 简洁的代码。

缺点:

  • 信息丢失。
  • 当数据丢失原因不明确时,难以调试。

正面案例

为结合测试结果和学生姓名,我们使用 zip_longest 并设置 fillvalue="n/a",保留了所有参与者的数据。

优点:

  • 明确显示缺失值。
  • 在处理过程中没有人被遗漏。

缺点:

  • 需要导入额外的模块。