2016-06-11 187 views
0

我想學習python reduce函數。int對象是不可迭代python

這是一些代碼,沒有任何意義,我

>>> x = [1,2,3] 
>>> reduce(sum, [b for b in x if b > 0]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'int' object is not iterable 
>>> reduce(sum, [b for b in x if b > 2]) 
3 

爲什麼它的工作當b> 2,但不是B> 0

的代碼看起來幾乎一模一樣

+0

您可能還需要學習'filter'玩,該列表理解是不必要的冗長 –

回答

1

摩西指出「總和消耗迭代器在第一次迭代」 讓我們用它

>>> sum(1,2) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'int' object is not iterable 

>>> sum([1,2]) 
3 
>>> sum(x) 
6 
>>> sum([b for b in x if b >0]) 
6 
>>> reduce(lambda x, y: x+y, x) 
6 
>>> reduce(lambda x, y: x+y, [b for b in x if b > 0]) 
6 
>>> reduce(lambda x, y: x+y, [b for b in x if b > 1]) 
5 
2

在第二種情況下,您使用列表理解創建的列表只有一個元素,所以它不會被減少。這種減少不會失敗,因爲在那裏沒有什麼可以減少的,所以函數總和不會被執行,也不會失敗。結果是唯一的整數,在那之前。
函數和在documentation中定義。正如你所看到的,它應該在一些可迭代的容器中求和,比如列表或元組。你可以編寫sum([1,2,3]),它就像你想要的那樣減少工作。如果你想使用約簡函數來實現這個結果,你必須確定你有一個函數,它需要兩個整數並返回它們的總和。

在這裏,你有這樣的功能:

def sum2(x, y): 
    return x + y 

具有這樣的功能,減少應該給您預期的結果。

sum2 = lambda x, y: x+y 

下面的函數相同,但更短,更好由於拉姆達符號,它可能是好的,它有時看起來在未來,如果你不知道它。

2

docsreduce

應用的2個參數功能累積到的迭代, 項目由左到右,從而減少可迭代爲單個值

因此,在第一種情況下,您通過使用內置sum錯誤地使用了reduce,它不包含兩個參數,而是iterablesumreduce的第一次迭代中消耗迭代並返回int,這不是進一步的可減少的


在第二種情況下,sum甚至沒有叫上迭代:

如果初始化中給出迭代只包含一個項目,則返回 第一個項目。

由於迭代是length 1,減少返回一個項目的迭代和sum沒有什麼。

1

reduce函數接受函數和迭代。
然後,它將可迭代的每個元素映射到該函數。


你的第一b > 0功能正在做的是試圖用2個參數運行sum。一個參數是累計總數,另一個是輸入列表的元素,例如它看起來像:sum(0, 1)

應用的兩個參數函數累計到迭代的項目,由左到右,從而減少可迭代爲單個值:
本文檔中列示。 ...左邊的參數是累積值和正確參數,是可迭代的更新值。


你的第二b > 2功能正在做的是簡單地運行減少含一個項目,不嘗試應用sum如文檔中規定的迭代器功能。

如果未給出初始化程序並且iterable只包含一個項目,則返回第一個項目。

但由於sum發生在一個迭代,你可以只是做:

sum([b for b in x if b > 0]) 
2

輸入的第二代碼片段是單元素的列表 - 這是一個退化的情況下可調用甚至沒有叫。

考慮下面的例子:

def my_sum(*args): 
    print "my_sum called with", args 
    return sum(*args) 


x = [1, 2, 3] 
reduce(my_sum, [b for b in x if b > 2]) 
# nothing gets printed, value 3 is returned, since it's only element in list 

現在考慮您的失敗案例:

reduce(my_sum, [b for b in x if b > 0]) 

輸出是:

my_sum called with (1, 2) 
[exception traceback] 

相當於調用內置的總和爲sum(1, 2),導致相同您引用的例外。

sum signature不遵循縮小功能的規則。 sum(iterable[, start])需要兩個參數(如預期),但其中第一個必須是可迭代,其中第二個是可選初始值。

reduce要求功能採取兩個參數,其中,(引用文檔):

左邊參數,x爲累積值和右參數, Y,從迭代的更新值。

我們可以清楚地看到這些接口是不一致的。正確的調用將是這樣的:

def reduce_sum(accumulator, new_value): 
    return accumulator + new_value 

reduce(reduce_sum, [b for b in x if b > 0]) 
相關問題