问题描述
本质上,它们是相同的功能-列表理解使用sum
代替x=0; x+=
,因为列表支持不支持后者.为什么列表理解的编译速度要慢40%?
Essentially these are the same functions - except list comprehension uses sum
instead of x=0; x+=
since the later is not supported. Why is list comprehension compiled to something 40% slower?
#list comprehension
def movingAverage(samples, n=3):
return [float(sum(samples[i-j] for j in range(n)))/n for i in range(n-1, len(samples))]
#regular
def moving_average(samples, n=3):
l =[]
for i in range(n-1, len(samples)):
x= 0
for j in range(n):
x+= samples[i-j]
l.append((float(x)/n))
return l
为了定时采样输入,我在[i*random.random() for i in range(x)]
For timing the sample inputs I used variations on [i*random.random() for i in range(x)]
推荐答案
您正在列表理解中使用生成器表达式:
You are using a generator expression in your list comprehension:
sum(samples[i-j] for j in range(n))
生成器表达式每次运行时都需要创建一个新框架,就像函数调用一样.这比较昂贵.
Generator expressions require a new frame to be created each time you run one, just like a function call. This is relatively expensive.
您根本不需要使用生成器表达式;您只需切片 samples
列表:
You don't need to use a generator expression at all; you only need to slice the samples
list:
sum(samples[i - n + 1:i + 1])
您可以指定第二个参数,即 sum()
的start
值. >功能;将其设置为0.0
以获得浮动结果:
You can specify a second argument, a start
value for the sum()
function; set it to 0.0
to get a float result:
sum(samples[i - n + 1:i + 1], 0.0)
这些变化共同带来了不同:
Together these changes make all the difference:
>>> from timeit import timeit
>>> import random
>>> testdata = [i*random.random() for i in range(1000)]
>>> def slow_moving_average(samples, n=3):
... return [float(sum(samples[i-j] for j in range(n)))/n for i in range(n-1, len(samples))]
...
>>> def fast_moving_average(samples, n=3):
... return [sum(samples[i - n + 1:i + 1], 0.0) / n for i in range(n-1, len(samples))]
...
>>> def verbose_moving_average(samples, n=3):
... l =[]
... for i in range(n-1, len(samples)):
... x = 0.0
... for j in range(n):
... x+= samples[i-j]
... l.append(x / n)
... return l
...
>>> timeit('f(s)', 'from __main__ import verbose_moving_average as f, testdata as s', number=1000)
0.9375386269966839
>>> timeit('f(s)', 'from __main__ import slow_moving_average as f, testdata as s', number=1000)
1.9631599469939829
>>> timeit('f(s)', 'from __main__ import fast_moving_average as f, testdata as s', number=1000)
0.5647804250038462
这篇关于Python:为什么列表理解比for循环慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!