Python迭代器和zip

pro*_*eek 5 python zip iterator

有了x = [1,2,3,4],我可以从中获得一个迭代器i = iter(x).

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

>>> i = iter(x)
>>> zip(i,i)
[(1, 2), (3, 4)]
Run Code Online (Sandbox Code Playgroud)

即使我可以使用此语法来获得相同的结果.

>>> zip(*[i] * 2)
[(1, 2), (3, 4)]
Run Code Online (Sandbox Code Playgroud)

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

mgi*_*son 10

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

当您打电话时zip(i, i),zip首先查看第一个流并取出一个项目.然后它查看第二个流(恰好是第一个流相同的流)并取出一个项目.然后它从这两个项目中生成一个元组并反复重复这个元素,直到流中没有任何内容.

也许更容易看出我是否zip在纯python中编写函数(为简单起见,只有2个参数).它看起来像1:

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

现在想象一下你所说的在哪里ab 是同一个对象的情况.在这种情况下,我们只next在迭代器上调用两次(i在你的示例中),它将i按顺序取出前两个项并将它们打包成一个元组.

一旦我们理解了为什么zip(i, i)会这样做,zip(*([i] * 2))就不会太难.让我们从里到外读出表达式......

[i] * 2
Run Code Online (Sandbox Code Playgroud)

这只是创建一个新的列表(长度为2),其中两个元素都是对迭代器的引用i.所以它是一样的zip(*[i, i])(当你想要重复超过2次的东西时,写起来会更方便). *解压缩是python中常见的习惯用法,您可以在python教程中找到更多信息.它的要点是python接受iterable并"解包"它,好像每个iterable项都是函数的一个单独的位置参数.所以:

zip(*[i, i])
Run Code Online (Sandbox Code Playgroud)

做同样的事情:

zip(i, i)
Run Code Online (Sandbox Code Playgroud)

而现在鲍勃是我们的叔叔.自从zip(i, i)讨论开始以来,我们刚刚全面展开.

1这个示例代码绝对简化,而不仅仅是前面提到的只接受2个参数.例如,zip可能会调用iter输入参数,以便它适用于任何可迭代(不仅仅是迭代器),但这应该足以得到重点...

  • 请记住,[`zip` 在 python2 中返回一个列表,在 python3 中返回一个迭代器](http://www.diveintopython3.net/porting-code-to-python-3-with-2to3.html#zip)。 (2认同)