EPY Effective Python 用 zip 函数同时遍历两个迭代器

本文介绍了如何在Python中使用zip函数同时遍历多个迭代器,以及如何改进代码清晰度。重点讲解了zip的惰性生成器特性,以及在处理不同长度迭代器时,zip_longest函数的作用。
摘要由CSDN通过智能技术生成

第 8 条 用 zip 函数同时遍历两个迭代器

书籍链接 O’Reilly书籍网站

在 Python 中,你经常会发现自己有许多与列表相关的对象。列表推导式可以轻松获取源列表并通过应用表达式获取派生列表:

>>> names = ["Cecilia", "Lise", "Marie"]
>>> counts = [len(n) for n in names]
>>> print(counts)
[7, 4, 5]
>>>

派生列表中的元素通过索引与源列表中的元素相关。要同时迭代两个列表,那么可以根据源列表的长度进行迭代:

>>> longest_name = None
>>> max_count = 0
>>> for i in range(len(names)):
...     count = counts[i]
...     if count > max_count:
...         longest_name = names[i]
...         max_count = count
...
>>> print(longest_name)
Cecilia
>>>

这种写法的问题在于,必须两次出现循环变量 i,这样代码变得不太好懂。改用 enumerate 实现可以好一点,但是仍然不够理想:

>>> for i, name in enumerate(names):
...     count = counts[i]
...     if count > max_count:
...         longest_name = name
...         max_count = count
...
>>>

为了使这段代码更清晰,Python 提供了 zip 内置函数。zip 使用惰性生成器包装两个或多个迭代器zip 生成器生成包含每个迭代器的下一个值的元组,这些元组可以直接在 for 语句中解包。生成的代码比索引多个列表的代码清晰得多:

>>> for name, count in zip(names, counts):
...     if count > max_count:
...         longest_name = name
...         max_count = count
...
>>>

zip 每次只从它封装的那些迭代器中各自取出一个元素,这意味着它可以与无限长的输入一起使用,而不会有程序使用过多内存和崩溃的风险。

但是,当输入迭代器的长度不同时,请注意 zip 的行为。

>>> names.append("Rosalind")
>>> for name, count in zip(names, counts):
...     print(name)
...
Cecilia
Lise
Marie
>>>

你会发现新添加的名称 Rosalind 没有打印。这就是 zip 的工作原理。它不断产生元组,直到任何一个包装的迭代器耗尽为止。它的输出与最短的输入一样长。当你知道迭代器具有相同的长度时,此方法可以正常工作。

但在许多其他情况下,zip 的截断行为是令人惊讶且糟糕的。如果你不希望传递给 zip 的列表的长度相等,请考虑使用 itertools 内置模块中的 zip_longest 函数:

>>> import itertools
>>>
>>> for name, count in itertools.zip_longest(names, counts, fillvalue=None):
...     print(f"{name}: {count}")
...
Cecilia: 7
Lise: 4
Marie: 5
Rosalind: None
>>> 

zip_longest 用传递给它的 fillvalue 替换缺失值,默认为 None

要点:

  • zip 内置函数可用于同时迭代多个迭代器。
  • zip 创建一个生成元组的惰性生成器,因此它可以用于无限长的输入。
  • 如果你为 zip 提供不同长度的迭代器,它会默默地将其输出为最短的迭代器。
  • 如果你想在不等长的迭代器上使用 zip 而不被截断,请使用 itertools 内置模块中的 zip_longest 函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值