如何使用ZIP并行处理迭代器


介绍

列表推导式使从源列表获取派生列表并应用表达式变得容易。例如,假设我想将列表中的每个元素乘以5。在这里,我使用简单的for循环来实现。

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
multiply_by_5 = []
for x in a:
multiply_by_5.append(x*5)
print(f"Output \n *** {multiply_by_5}")

输出

*** [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]

使用列表推导式,我可以通过指定表达式和要循环遍历的输入序列来获得相同的结果。

# List comprehension
multiply_by_5 = [x*2 for x in a]
print(f"Output \n *** {multiply_by_5}")

输出

*** [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

现在,假设您有两个列表需要相加。

# 1 . Create a List of Numbers
list1 = [100, 200, 300, 400]
list2 = [500, 600, 700, 800]

# 2. Add the two lists to create a new list
list3 = []

# Using a Loop.
for i in range(len(list1)):
added_value = list1[i] + list2[i]
list3.append(added_value)
print(f"Output \n*** {list3}")

输出

*** [600, 800, 1000, 1200]

现在,这里重要的是,派生列表(在本例中为list3)中添加的值与源列表中的项通过其索引直接相关。

现在,就压缩而言,这是针对相同列表整数的压缩解决方案。在这种情况下,两个整数列表,一个包含100、200、300和400,另一个包含500、600、700和800。当然,我们可以定义它们并将它们赋给变量。它们不必是列表。

它们可以是其他序列,例如元组等等。

因此,我们将要做的就是将这些元素对从列表中压缩在一起,因此list1中的100和list2中的500将被压缩在一起,依此类推。对于每个元组,当我们遍历它们时,我们将把元组解包到变量a和b中。

list4 = []
list4 = [(a + b) for a, b in zip(list1, list2)]
print(f"Output \n*** {list4}")

输出

*** [600, 800, 1000, 1200]

上面的解决方案看起来很酷,但是在你将它们应用到你的代码中之前,你需要知道一个严重的问题。

如果输入迭代器的长度不同,内置函数zip的行为很奇怪。让我们尝试一下。

# add a new number to the list
list1.append(1000)
print(f"Output \n*** Length of List1 is {len(list1)} , Length of List2 is {len(list2)}")

# run the zip against the list for addition.
list5 = [(a + b) for a, b in zip(list1, list2)]
print(f"*** {list5}")

输出

*** Length of List1 is 9 , Length of List2 is 4
*** [600, 800, 1000, 1200]

现在,当我们打印出list3中的每个添加的数字时,你会注意到添加到list1的数字不见了,即使我们把它添加到那里,它也在list1中,但在zip的输出中却没有显示。

这就是zip的工作方式。它会让你保持在元组中,直到任何一个迭代器用尽。因此,即使list1比list2还有更多内容,它也会先用尽,然后循环退出。

令人惊讶的是,你不会收到任何异常通知。因此,在生产环境中必须非常小心使用zip。

在python函数中,你有一个来自itertools的选项,叫做zip_longest。

zip_longest的作用是,即使其中一个迭代器用尽了,它也会继续。

from itertools import zip_longest

list6 = []
for a, b in zip_longest(list1, list2):
if b is None:
print(f" << do your logic here >> ")
elif a is None:
print(f" << do your logic here >> ")
else:
list6.append(a + b)
print(f"Output \n*** {list6}")


<< do your logic here >>
<< do your logic here >>
<< do your logic here >>
<< do your logic here >>
<< do your logic here >>

输出

*** [600, 800, 1000, 1200]

结论

  • 如果你想并行迭代多个迭代器,zip函数非常方便。

  • 当传递不同长度的迭代器时,zip函数的工作方式不同。

  • 如果你想使用不同长度的迭代器,那么使用zip_longest。

更新于:2020年11月9日

281 次浏览

开启你的职业生涯

完成课程获得认证

开始学习
广告