Python:为什么列表理解比for循环慢 [英] Python: Why is list comprehension slower than for loop

查看:242
本文介绍了Python:为什么列表理解比for循环慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

本质上,它们是相同的功能-列表理解使用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循环慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆