2013-05-16 29 views
3

有人可以解釋爲什麼這些在Python 2.7.4中輸出不同的東西嗎?他們在python 3.3.1中輸出相同的東西。我只是想知道這是否是2.7版本中修正爲3的錯誤,或者是由於語言的某些變化。zip和groupby在python中的好奇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] 
+0

偉大的問題!它讓我難住了幾分鐘... – mgilson

回答

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) 
+0

更好的方式是使用導入語法來使'zip'懶 - 不記得語法ottomh –

+0

@JonClements - 我不知道我知道你是什麼提到,但我現在很好奇。我打開了關於它的Code Review問題。 http://codereview.stackexchange.com/questions/26271/cleaner-way-to-import-izip-for-different-versions-of-python – mgilson

+0

爲了使'zip'懶惰'試試:從itertools import izip as zip '等等,這對我來說更有意義,因爲那麼其餘的代碼在2.x和3.x中都是一樣的(無論如何)。 – martineau