2012-07-04 31 views
3

的名單減少什麼是錯的?:以下如何使用與列表

lss = reduce(list.extend, [[1],[2]], []) 

原因:

Traceback (most recent call last): 
    File "<pyshell#230>", line 1, in <module> 
    lss = reduce(list.extend, [[1],[2]], []) 
TypeError: descriptor 'extend' requires a 'list' object but received a 'NoneType' 

我不知道其中NoneType的來源。

+0

什麼是你想要的結果/什麼列表中你想擴展? –

回答

13

試試這個:

lss = reduce(lambda acc, ele : acc + ele, [[1],[2]], []) 

lss 
> [1, 2] 

的問題是,extend()回報None(這也正是NoneType是從哪裏來的),而不會跟你想要做什麼工作 - 傳遞給reduce()功能必須返回一個值:到目前爲止的累計結果。

+0

我意識到我可以做到這一點。我仍然想知道使用list.extend方法時出了什麼問題。它似乎應該工作。 - 你的編輯回答了這個。 – cammil

+1

@cammil正如我上面提到的:'extend()'將_always_返回'None';對於'reduce()'來執行被執行的函數_has to_返回一個值:到目前爲止的累計結果。 –

+2

如果有人想知道*爲什麼* list.extend()返回None:這是因爲在Python中,修改數據結構的函數總是返回None,因爲Python遵守Command/Query Separation。 http://en.wikipedia.org/wiki/Command-query_separation – steveha

5

我認爲這值得一提的是:

sum([[1],[2]], []) 

也將工作,而且我敢肯定會更快然後通過一個lambda減少。

我很好奇的不同方法的速度,所以我做了一些測試:

reduce(lambda a,b:a+b, x, [])    3644.38161492 
reduce(list.__add__, x, [])     3609.44079709 
sum(x,[])         3526.84987307 
y = [];for z in x: y.extend(z)    143.370306969 
y = [];map(y.extend,x)      71.7020270824 
y = [None]*400;del y[:];map(y.extend,x)  66.2245891094 
list(itertools.chain(*x))     102.285979986 
list(itertools.chain.from_iterable(x))  96.6231369972 
[a for b in x for a in b]     203.764872074 

而且在PyPy(因爲,爲什麼不)

reduce(lambda a,b:a+b, x, [])    4797.5895648 
reduce(list.__add__, x, [])     4794.01214004 
sum(x,[])         4748.02929902 
y = [];for z in x: y.extend(z)    56.9253079891 
y = [];map(y.extend,x)      73.8642170429 
y = [None]*400;del y[:];map(y.extend,x)  152.157783031 
list(itertools.chain(*x))     633.854824066 
list(itertools.chain.from_iterable(x))  629.917827129 
[a for b in x for a in b]      89.6922459602 

x = [[1,2,3,4],[2,3,4,5],[3,4,5,6],[4,5,6,7],[5,6,7,8],[6,7,8,9],[7,8,9,10],[8,9,10,11]]*100 

結論:

  1. 在你減少使用拉姆達是慢
  2. 專業sum功能更快然後減少
  3. 添加列表很慢。
  4. Python循環開銷很大。
+0

如果你設置x = x * 100,你可以開始看到算法之間的實際速度差異。 – DSM

+0

@DSM,你是對的,所以我這樣做了。 –

+0

+1有趣的時機 – jamylak

1

正如ÓscarLópez所述,list.extend返回None,因此不能與reduce一起使用。另外的建議使用lambda功能,您還可以使用list.__add__reduce

>>> reduce(list.__add__, [[1],[2]], []) 
[1, 2] 
1

您可能需要使用itertools.chain

請返回從第一個迭代的元素,直到 一個迭代它被耗盡,然後繼續下一個迭代,直到所有的迭代器都耗盡。用於將連續序列作爲 單一序列進行處理。等效於:

def chain(*iterables): 
    # chain('ABC', 'DEF') --> A B C D E F 
    for it in iterables: 
     for element in it: 
      yield element