Python 如何在列表列表中使用reduce

Python 如何在列表列表中使用reduce,python,list,python-2.7,Python,List,Python 2.7,以下内容有什么问题 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 bu

以下内容有什么问题

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'
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
lss=reduce(list.extend、[[1]、[2]]、[]
TypeError:描述符“extend”需要一个“list”对象,但收到了一个“NoneType”
我不确定
NoneType
是从哪里来的。

试试这个:

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

lss
> [1, 2]

问题是返回的是
None
(这就是
NoneType
的来源),这与您想要执行的操作无关-传递给的函数必须返回一个值:到目前为止的累积结果。

我认为值得注意的是:

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很慢
  • 专用的
    sum
    函数比reduce更快
  • 添加列表很慢
  • Python循环开销很大

  • 正如奥斯卡·洛佩斯所指出的,
    list.extend
    返回
    None
    ,因此不能与
    reduce
    一起使用。除了建议使用
    lambda
    功能外,您还可以使用
    list.\uu添加\uuuu
    reduce

    >>> reduce(list.__add__, [[1],[2]], [])
    [1, 2]
    
    您可能想使用

    生成一个迭代器,从第一个iterable返回元素,直到 它已耗尽,然后继续下一个iterable,直到所有 人们都筋疲力尽了。用于将连续序列作为一个整体处理 单一序列。相当于:


    我意识到我能做到。我仍然想知道使用list.extend方法有什么问题。看来它应该有用您的编辑回答了这个问题。@cammil正如我上面提到的:
    extend()
    将始终返回
    None
    ;要使
    reduce()
    工作,执行的函数必须返回一个值:到目前为止的累积结果。如果有人想知道为什么
    list.extend()
    返回
    None
    :这是因为在Python中,改变数据结构的函数总是返回
    None
    ,因为Python遵循命令/查询分离。你想要的结果是什么?/你想扩展什么列表?如果你设置x=x*100,你就可以开始看到算法之间的实际速度差异。不幸的是,这个基准中缺少的是:
    列表(itertools.chain.from_iterable(x))
    [b代表x中的a代表a中的b]
    。第一种可能是最快的选择。@SvenMarnach,他们补充道。然而,我的结果显示它们都比一些现有的选项慢。在我测试的两台机器上,
    list(itertools.chain.from_iterable(x))
    始终比
    list(itertools.chain(*x))
    快,而且对于没有示例列表人为高缓存局部性的较大列表来说,这是一个很大的差距(这是由于
    *100
    重复使用了数百次相同的列表造成的)。它确实比
    y=[];map(y.extend,x)
    慢。有趣的帖子!@SvenMarnach,我继续并重新运行了所有测试,我的结果现在符合您的经验。
    >>> reduce(list.__add__, [[1],[2]], [])
    [1, 2]
    
    def chain(*iterables):
        # chain('ABC', 'DEF') --> A B C D E F
        for it in iterables:
            for element in it:
                yield element