我写了一个测试速度的简单脚本,这就是我发现的。实际上for循环在我的情况下是最快的。这真让我感到惊讶,请查看贝娄(正在计算平方和)。那是因为它在内存中保存列表还是有意?任何人都可以解释这一点。
from functools import reduce
import datetime
def time_it(func, numbers, *args):
start_t = datetime.datetime.now()
for i in range(numbers):
func(args[0])
print (datetime.datetime.now()-start_t)
def square_sum1(numbers):
return reduce(lambda sum, next: sum+next**2, numbers, 0)
def square_sum2(numbers):
a = 0
for i in numbers:
i = i**2
a += i
return a
def square_sum3(numbers):
sqrt = lambda x: x**2
return sum(map(sqrt, numbers))
def square_sum4(numbers):
return(sum([i**2 for i in numbers]))
time_it(square_sum1, 100000, [1, 2, 5, 3, 1, 2, 5, 3])
time_it(square_sum2, 100000, [1, 2, 5, 3, 1, 2, 5, 3])
time_it(square_sum3, 100000, [1, 2, 5, 3, 1, 2, 5, 3])
time_it(square_sum4, 100000, [1, 2, 5, 3, 1, 2, 5, 3])
0:00:00.302000 #Reduce
0:00:00.144000 #For loop
0:00:00.318000 #Map
0:00:00.290000 #List comprehension`
更新 - 当我尝试更长的循环时,会有结果。
time_it(square_sum1, 100, range(1000))
time_it(square_sum2, 100, range(1000))
time_it(square_sum3, 100, range(1000))
time_it(square_sum4, 100, range(1000))
0:00:00.068992
0:00:00.062955
0:00:00.069022
0:00:00.057446
答案 0 :(得分:2)
Python function calls have overheads使得它们相对较慢,因此使用简单表达式的代码总是比在函数中包装该表达式的代码更快;它是正常的def
函数还是lambda
并不重要。出于这个原因,如果您要在map
循环中使用普通表达式执行相同的工作,或者如果您要将它们传递给Python函数,则最好避免使用reduce
或for
。理解或生成器表达。
有一些小的优化可以加快你的一些功能。不要做出不必要的任务。例如,
def square_sum2a(numbers):
a = 0
for i in numbers:
a += i ** 2
return a
此外,i * i
比i ** 2
快一点,因为乘法比取幂更快。
正如我在评论中提到的,传递sum
生成器比列表理解更有效,特别是如果循环很大;它可能不会对长度为8的小列表产生影响,但是对于大型列表来说它会非常明显。
sum(i*i for i in numbers)
顺便说一句,你不应该使用sum
或next
作为变量名,因为它会掩盖具有相同名称的内置函数。它不会伤到任何东西,但它仍然不是一个好主意,它使你的代码在编辑器中看起来很奇怪,语法高亮比SO语法高亮显示更加全面。
以下是使用timeit
模块的新版代码。它每次重复10,000次循环并对结果进行排序。正如timeit docs中所解释的那样,重复系列中要看的重要数字是最小的。
在典型情况下,最低值给出了速度的下限 你的机器可以运行给定的代码片段;更高的价值观 结果向量通常不是由Python的可变性引起的 速度,但通过其他过程干扰您的计时准确性。 所以结果的
min()
可能是你应该唯一的数字 感兴趣的。
from timeit import Timer
from functools import reduce
def square_sum1(numbers):
return reduce(lambda total, u: total + u**2, numbers, 0)
def square_sum1a(numbers):
return reduce(lambda total, u: total + u*u, numbers, 0)
def square_sum2(numbers):
a = 0
for i in numbers:
i = i**2
a += i
return a
def square_sum2a(numbers):
a = 0
for i in numbers:
a += i * i
return a
def square_sum3(numbers):
sqr = lambda x: x**2
return sum(map(sqr, numbers))
def square_sum3a(numbers):
sqr = lambda x: x*x
return sum(map(sqr, numbers))
def square_sum4(numbers):
return(sum([i**2 for i in numbers]))
def square_sum4a(numbers):
return(sum(i*i for i in numbers))
funcs = (
square_sum1,
square_sum1a,
square_sum2,
square_sum2a,
square_sum3,
square_sum3a,
square_sum4,
square_sum4a,
)
data = [1, 2, 5, 3, 1, 2, 5, 3]
def time_test(loops, reps):
''' Print timing stats for all the functions '''
timings = []
for func in funcs:
fname = func.__name__
setup = 'from __main__ import data, ' + fname
cmd = fname + '(data)'
t = Timer(cmd, setup)
result = t.repeat(reps, loops)
result.sort()
timings.append((result, fname))
timings.sort()
for result, fname in timings:
print('{0:14} {1}'.format(fname, result))
loops, reps = 10000, 3
time_test(loops, reps)
<强>输出强>
square_sum2a [0.03815755599862314, 0.03817843700016965, 0.038571521999983815]
square_sum4a [0.06384095800240175, 0.06462285799716483, 0.06579178199899616]
square_sum3a [0.07395686000018031, 0.07405958899835241, 0.07463337299850537]
square_sum1a [0.07867341000019223, 0.0788448769999377, 0.07908406700153137]
square_sum2 [0.08781023399933474, 0.08803317899946705, 0.08846573399932822]
square_sum4 [0.10260082300010254, 0.10360279499946046, 0.10415067900248687]
square_sum3 [0.12363515399920288, 0.12434166299863136, 0.1273790529994585]
square_sum1 [0.1276186039976892, 0.13786184099808452, 0.16315817699796753]
结果是在Linux上运行Python 3.6.0的旧单核32位2GHz机器上获得的。
答案 1 :(得分:1)
这几乎与底层编程语言无关,因为抽象不是免费的。
含义:调用方法总是有一定的成本。需要建立堆栈;控制流程需要“跳跃”。当您考虑较低级别时,例如CPU:可能需要加载该方法的代码,依此类推。
换句话说:当您的主要要求是硬核数字运算时,您必须平衡易用性和相应抽象的成本。
超越:如果你专注于速度,那么你应该超越python,或者至少超越“普通”python。相反,您可以转向numpy等模块。