循环求和与总结列表理解

时间:2014-12-18 05:11:02

标签: python

在我做的那种计算中,我经常遇到需要在(至少)一个列表上加总一些表达式。让我们说我想在某些列表L中找到x的x ^ 2之和。

的运行时间之间是否存在显着差异
sum([val**2 for val in L])

total = 0
for val in L:
    total+=val**2

如果我有一个更复杂的表达式,这会改变吗?我并不关心与创建列表相关的内存问题,而是更清晰的代码和更快的运行时间。

我基本上想知道人们对列出生成器和求和的概率是否会给我一个更快的代码 - 在C而不是python中进行循环。

编辑对于任何搜索此问题的人来说,答案结果是转换为numpy数组然后进行计算是最快的。

2 个答案:

答案 0 :(得分:4)

最简单,最确定的答案就是测试它:

import timeit
import numpy as np

L = range(1000)
M = np.arange(1000)

def f0():
    sum([val**2 for val in L])

def f1():
    total = 0
    for val in L:
        total+=val**2    

def f2():
    np.sum(M*M)

print timeit.timeit("f0()", setup="from __main__ import f0, f1, f2, L, M", number=100)
print timeit.timeit("f1()", setup="from __main__ import f0, f1, f2, L, M", number=100)
print timeit.timeit("f2()", setup="from __main__ import f0, f1, f2, L, M", number=100)

# 0.015289068222
# 0.00959897041321
# 0.000958919525146

如果使用1M而不是1K,那么时间的比例相似(这里我也使用了number=10,所以我没有等待):

# 1.21456193924
# 1.08847117424
# 0.0474879741669

也就是说,两种纯Python方法大致相同,使用numpy可以将计算速度提高10-20倍。

答案 1 :(得分:0)

根据汤姆的回答,我想包括创建np数组的成本,并进行更公平的比较,我可能会迭代2个循环。所以我在这里将x * y总结为两个列表。

import timeit
import numpy as np

X = range(10000)
Y = range(10000)
M = np.arange(10000)
N = np.arange(10000)

def f0():
    sum([x*y for x in X for y in Y])

def f1():
    sum(x*y for x in X for y in Y)

def f2():
    total = 0
    for x in X:
        for y in Y:
            total += x*y

def f3():
    np.sum(np.array(X)*np.array(Y))

def f4():
    np.sum(M*N)



print timeit.timeit("f0()", setup="from __main__ import f0, f1, f2, f3, f4, X, Y, M, N", number=10)
print timeit.timeit("f1()", setup="from __main__ import f0, f1, f2, f3, f4, X, Y, M, N", number=10)
print timeit.timeit("f2()", setup="from __main__ import f0, f1, f2, f3, f4, X, Y, M, N", number=10)
print timeit.timeit("f3()", setup="from __main__ import f0, f1, f2, f3, f4, X, Y, M, N", number=10)
print timeit.timeit("f4()", setup="from __main__ import f0, f1, f2, f3, f4, X, Y, M, N", number=10)

#73.9396169186
#68.8783578873
#61.4824860096
#0.00859999656677
#0.000278949737549

因此,与Python中的循环相比,答案是列表理解最慢约15-20%。

如果我们已经将它设置为numpy,那么它比创建numpy数组所需的时间快30倍。创建numpy数组并在numpy中执行它会使数量级的纯python击败 - 这让我感到惊讶。我想它不应该有。