带有迭代器的Python zip函数与可迭代的[duplicate]

问题描述 投票:4回答:3

当传递iterator而不是iterable时,我无法理解python中zip()函数的工作方式。

看看这两个打印语句:

string = "ABCDEFGHI"

print(list(zip(*[iter(string)] * 3)))
# Output: [('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'H', 'I')]

print(list(zip(*[string] * 3)))
# Output: [('A', 'A', 'A'), ('B', 'B', 'B'), ('C', 'C', 'C'), ('D', 'D', 'D'), ('E', 'E', 'E'), ('F', 'F', 'F'), ('G', 'G', 'G'), ('H', 'H', 'H'), ('I', 'I', 'I')]

有人可以在两种情况下解释我zip()的工作吗?

python python-3.x
3个回答
4
投票

区别在于,对于[iter(string)] * 3zip创建单个迭代器的别名。对于[string] * 3zip为每个参数创建唯一的迭代器。没有重复的较短输出是zip耗尽了单个别名迭代器。

有关what is meaning of [iter(list)]*2 in python?的工作方式以及可能导致意想不到的结果的更多详细信息,请参见[iter(...)] * 2。>

如果List of lists changes reflected across sublists unexpectedly混叠行为令人惊讶,请参阅规范答案[...] * 3。>

为了正确理解这一点,首先请确保您了解相关的基础知识:Python的iterator protocolobject identity versus equality

print(list(zip(*[string] * 3)))

我们计算列表[string] * 3,并将该列表中的每个元素传递给zip,因此就好像我们编写了zip(string, string, string)一样。 Python为每个参数隐式创建一个单独的迭代器(即使在每种情况下它都是相同的字符串对象-不能复制!),并且每个参数都对同一字符串进行迭代。第一次,每个迭代器都会找到'A',依此类推。

print(list(zip(*[iter(string)] * 3)))

现在,我们为字符串创建了一个迭代器,并将其在三个参数位置传递给zip。在每种情况下,Python的迭代逻辑都会尝试为该迭代器“创建一个迭代器”。但是迭代器的迭代器本身就是

(不是其副本!)。因此,一旦迭代开始,zip将使用相同的迭代器对象3次来创建其每个输出。并且每次它从迭代器中获取next元素时,都会受到先前尝试的影响。因此,第一次,zip向同一迭代器请求三个元素,并获得'A''B''C'

让我们使用一个更清晰的示例:

a = iter("123456")  # One iterator 
list(zip(a, a, a)) 
# [('1', '2', '3'), ('4', '5', '6')]

vs

a = iter("123456")
b = iter("123456")
c = iter("123456")
list(zip(a, b, c))
# [('1', '1', '1'), ('2', '2', '2'), ('3', '3', '3'), ('4', '4', '4'), ('5', '5', '5'), ('6', '6', '6')]

显然,在第一个示例中,a只能产生6个元素,并且每当zip需要创建值时,都必须产生3到zip。相比之下,第二个示例总共有18个元素,并以3为6组的形式产生它们。


2
投票

为了正确理解这一点,首先请确保您了解相关的基础知识:Python的iterator protocolobject identity versus equality


2
投票

让我们使用一个更清晰的示例:

© www.soinside.com 2019 - 2024. All rights reserved.