Python 迭代器和 zip

标签 python iterator python-zip

使用 x = [1,2,3,4],我可以从 i = iter(x) 获取迭代器。

有了这个迭代器,我可以使用 zip 函数创建一个包含两个项目的元组。

>>> i = iter(x)
>>> zip(i,i)
[(1, 2), (3, 4)]

即使我可以使用这种语法来获得相同的结果。

>>> zip(*[i] * 2)
[(1, 2), (3, 4)]

这是如何运作的?带有 zip(i,i)zip(*[i] * 2) 的迭代器如何工作?

最佳答案

迭代器就像一个项目流。您一次只能查看流中的一个项目,并且您只能访问第一个元素。要查看流中的某些内容,您需要将其从流中移除,一旦您从流的顶部取出某些内容,它就会永远从流中消失。

当您调用 zip(i, i) 时,zip 首先查看第一个流并取出一个项目。然后它查看第二个流(恰好与第一个流相同的流)并取出一个项目。然后它从这两个项目中生成一个元组并一遍又一遍地重复这个过程,直到流中没有任何东西为止。

如果我用纯 python 编写 zip 函数(为简单起见,只有 2 个参数),也许会更容易看出。它看起来像1:

def zip(a, b):
    out = []
    try:
        while True:
            item1 = next(a)
            item2 = next(b)
            out.append((item1, item2))
    except StopIteration:
        return out

现在想象一下您正在讨论 ab 是同一个对象 的情况。在这种情况下,我们只需在迭代器上调用 next 两次(在您的示例中为 i ),它只会从 i 中获取前两项按顺序将它们打包成一个元组。

一旦我们理解了为什么 zip(i, i) 的行为方式,zip(*([i] * 2)) 就不太一样了难的。让我们从内到外阅读表达式...

[i] * 2

这只是创建了一个新列表(长度为 2),其中两个元素都是对迭代器 i 的引用。所以它和 zip(*[i, i]) 是一样的(只是当你想重复某件事超过 2 次时写起来更方便)。 * 解包是 python 中的常见习惯用法,您可以在 the python tutorial 中找到更多信息。 .它的要点是 python 获取可迭代对象并将其“解包”,就好像可迭代对象的每个项目都是函数的一个单独的位置参数。所以:

zip(*[i, i])

做同样的事情:

zip(i, i)

现在 Bob 是我们的叔叔了。我们刚刚绕了一圈,因为 zip(i, i) 是讨论的起点。

1这个示例代码肯定比前面提到的只接受 2 个参数更简单。例如,zip 可能会在输入参数上调用 iter 以便它适用于任何可迭代对象(不仅仅是迭代器),但这应该足以说明问题跨越...

关于Python 迭代器和 zip,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38024554/

相关文章:

参数化类型的空集合上的 Java 迭代器

C++:如何获取 vector 来打印用户输入?

python - 如何在 python 中使用 zip 和列表理解来展平 2D 列表并添加分隔符?

python - 解压缩导致 ValueError 的 zip 对象

python - 过滤数据框并根据给定条件添加新列

python - 如何在for循环if语句中处理 “SettingWithCopyWarning”

python - Alembic SQLAlchemy 自动生成元数据错误

python - 运行使用 Python 创建的命令行工具

c++ - C++ 中的 IEnumerable?

Python - 为什么 enumerate() 导致稍后的 zip() 仅从列表中的最后一项中提取?