可以在列表上加快速度

时间:2017-03-04 08:34:22

标签: python performance list sum

这是对此question

的后续行动

首先,您会注意到您无法在字符串列表上执行sum来连接它们,python告诉您使用str.join代替它,这样做很好建议,因为无论你如何在字符串上使用+,性能都很差。

"无法使用sum"限制不适用于list,但itertools.chain.from_iterable是执行此类列表展平的首选方式。

但是sum(x,[]) x是一个列表清单时确实很糟糕。

但它应该保持这种状态吗?

我比较了3种方法

import time
import itertools

a = [list(range(1,1000)) for _ in range(1000)]

start=time.time()
sum(a,[])
print(time.time()-start)

start=time.time()
list(itertools.chain.from_iterable(a))
print(time.time()-start)


start=time.time()
z=[]
for s in a:
    z += s
print(time.time()-start)

结果:

    列表清单中的
  • sum():10.46647310256958。好的,我们知道。
  • itertools.chain:0.07705187797546387
  • 使用就地添加的自定义累计金额:0.057044029235839844(如您所见,可能比itertools.chain更快)

因此sum落后于result = result + b而不是result += b

现在我的问题是:

为什么sum可以使用这种累积方法?

(这对于现有的应用程序是透明的,并且可以使用sum内置的内容来有效地展平列表)

3 个答案:

答案 0 :(得分:6)

我们可以尝试使 sum()变得更聪明,但Alex Martelli和Guido van Rossum希望将其专注于算术总结。

FWIW,你应该通过这个简单的代码获得合理的性能:

result = []
for seq in mylists:
    result += seq

对于你的另一个问题,“为何不能在可用时使用这种累积方法?”,请参阅Python / bltinmodule.c中对builtin_sum()的评论:

    /* It's tempting to use PyNumber_InPlaceAdd instead of
       PyNumber_Add here, to avoid quadratic running time
       when doing 'sum(list_of_lists, [])'.  However, this
       would produce a change in behaviour: a snippet like

         empty = []
         sum([[x] for x in range(10)], empty)

       would change the value of empty. */

答案 1 :(得分:1)

/* It's tempting to use PyNumber_InPlaceAdd instead of
           PyNumber_Add here, to avoid quadratic running time
           when doing 'sum(list_of_lists, [])'.  However, this
           would produce a change in behaviour: a snippet like
             empty = []
             sum([[x] for x in range(10)], empty)
           would change the value of empty. */
temp = PyNumber_Add(result, item);

取自Python的内置源代码https://github.com/python/cpython/blob/master/Python/bltinmodule.c#L2146 行:2342

答案 2 :(得分:1)

FWIW,我们可以通过将适当的自定义类实例作为sum arg传递给start来欺骗解释器让我们对字符串使用sum

class Q(object):
    def __init__(self, data=''):
        self.data = str(data)

    def __str__(self):
        return self.data

    def __add__(self, other):
        return Q(self.data + str(other))

print(sum(['abc', 'def', 'ghi'], Q()))

<强>输出

abcdefghi

当然,这个 是一件相当愚蠢的事情。 :)