在Python 2.7中的zip和groupby好奇心

时间:2013-05-16 22:04:25

标签: python python-2.7 python-3.x

有人可以解释为什么这些在Python 2.7.4中输出不同的东西吗?它们在python 3.3.1中输出相同的内容。我只是想知道这是否是2.7中的错误,修复了3,或者是否是由于语言的某些变化。

>>> for (i,j),k in zip(groupby([1,1,2,2,3,3]), [4,5,6]):
...     print list(j)
... 
[]
[]
[3]
>>> for i,j in groupby([1,1,2,2,3,3]):
...     print list(j)
... 
[1, 1]
[2, 2]
[3, 3]

1 个答案:

答案 0 :(得分:6)

这不是一个错误。它与groupby iterable消耗时有关。使用python3尝试以下操作,您将看到相同的行为:

from itertools import groupby
for (i,j),k in list(zip(groupby([1,1,2,2,3,3]), [4,5,6])):
    print (i,list(j),k)

请注意,如果删除外部list,则会获得预期的结果。这里的“问题”是石斑鱼对象(在j中返回)是一个可迭代的,只要它们是相同的就会产生元素。它不会提前知道它会产生什么或有多少元素。它只接收一个可迭代的输入,然后从该可迭代得到。如果你继续前进到下一个“组”,那么在你有机会查看元素之前,迭代最终会消耗掉。这是一个设计决策,允许groupby对可产生任意(甚至无限)数量的元素的迭代进行操作。

在python2.x中,zip将创建一个列表,在循环开始之前有效地移过每个“组”。在这样做时,它最终会消耗groupby返回的每个“组”对象。这就是您只报告列表中最后一个元素的原因。 python2.x的修复是使用itertools.izip而不是zip。在python3.x中,izip成为内置zip。在我看来,在这个脚本中支持两者的唯一方法是通过以下方式:

from __future__ import print_function
from itertools import groupby
try:
    from itertools import izip
except ImportError:  #python3.x
    izip = zip

for (i,j),k in izip(groupby([1,1,2,2,3,3]), [4,5,6]):
    print (i,list(j),k)