【问题标题】:zip and groupby curiosity in python 2.7python 2.7中的zip和groupby好奇心
【发布时间】:2013-05-16 22:04:24
【问题描述】:

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

>>> 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]

【问题讨论】:

  • 好问题!它让我难倒了几分钟......

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


【解决方案1】:

这不是错误。它与 groupby 迭代何时被消耗有关。使用 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,那么您会得到您期望的结果。这里的“问题”是 grouper 对象(在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)

【讨论】:

  • 更好的方法是使用导入语法使 zip 变得懒惰 - 不记得语法 ottomh
  • @JonClements -- 我不确定我知道你指的是什么,但我现在很好奇。我打开了一个关于它的代码审查问题。 codereview.stackexchange.com/questions/26271/…
  • zip 变得懒惰只是try: from itertools import izip as zip 等。这对我来说更有意义,因为其余的代码在 2.x 和 3.x 中的工作方式相同(无论如何都要写这个) )。
  • @martineau -- 是的,我也用过那个……基本上归结为你是想从 python2.x 的角度还是从 python3.x 的角度来看待事物。
  • @JonClements -- 我刚刚又看到了这个。我想你可能指的是from future_builtins import zip,它从 python2.6 IIRC 开始工作
猜你喜欢
  • 2013-07-25
  • 2015-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多