迭代器就像一个项目流.您只能一次查看流中的项目,并且只能访问第一个元素.要查看流中的某些内容,您需要将其从流中删除,一旦您从流的顶部获取内容,它就会从流中消失.
当您调用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
现在假设你在谈论a和b是同一个对象的情况.在这种情况下,我们只需在迭代器上调用next两次(在你的示例中为i),它将依次从i中取出前两个项并将它们打包成一个元组.
一旦我们理解为什么zip(i,i)的行为方式如此,zip(*([i] * 2))就不会太难了.让我们从里到外读出表达式……
[i] * 2
这只是创建一个新的列表(长度为2),其中两个元素都是对迭代器i的引用.所以它与zip(* [i,i])是一样的(当你想要重复超过2次的东西时,写起来会更方便). *解压缩是python中常见的习惯用法,你可以在the python tutorial中找到更多信息.它的要点是python接受iterable并“解包”它,好像每个iterable项都是函数的一个单独的位置参数.所以:
zip(*[i, i])
做同样的事情:
zip(i, i)
而现在鲍勃是我们的叔叔.由于zip(i,i)是本次讨论开始的地方,我们刚刚全面展开.
1这个示例代码绝对简化,而不仅仅是前面提到的只接受2个参数.例如,zip可能会在输入参数上调用iter,这样它就可以用于任何可迭代的(不仅仅是迭代器),但这应该足以得到重点…