这是对此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 itertools.chain
更快)因此sum
落后于result = result + b
而不是result += b
现在我的问题是:
为什么sum
可以使用这种累积方法?
(这对于现有的应用程序是透明的,并且可以使用sum
内置的内容来有效地展平列表)
答案 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
当然,这个 是一件相当愚蠢的事情。 :)