当前位置: 首页 > 面试题库 >

Python内置求和函数与循环性能对比

苏运良
2023-03-14
问题内容

我注意到,sum在对1000000个整数列表求和时,Python的内置函数比for循环快大约3倍:

import timeit

def sum1():
    s = 0
    for i in range(1000000):
        s += i
    return s

def sum2():
    return sum(range(1000000))

print 'For Loop Sum:', timeit.timeit(sum1, number=10)
print 'Built-in Sum:', timeit.timeit(sum2, number=10)

# Prints:
# For Loop Sum: 0.751425027847
# Built-in Sum: 0.266746997833

这是为什么?如何sum执行?


问题答案:

速度差实际上大于3倍,但是您首先通过创建一个巨大的内存列表(一百万个整数)来降低这两个版本的速度。将其与时间试用分开:

>>> import timeit
>>> def sum1(lst):
...     s = 0
...     for i in lst:
...         s += i
...     return s
... 
>>> def sum2(lst):
...     return sum(lst)
... 
>>> values = range(1000000)
>>> timeit.timeit('f(lst)', 'from __main__ import sum1 as f, values as lst', number=100)
3.457869052886963
>>> timeit.timeit('f(lst)', 'from __main__ import sum2 as f, values as lst', number=100)
0.6696369647979736

现在,速度差已超过5倍。

for环所解释的Python字节码执行。sum()完全以C代码循环。解释的字节码和C代码之间的速度差异很大。

另外,如果C代码可以将总和保留在C类型中,则确保不创建新的Python对象;这适用于intfloat结果。

反汇编的Python版本执行以下操作:

>>> import dis
>>> def sum1():
...     s = 0
...     for i in range(1000000):
...         s += i
...     return s
... 
>>> dis.dis(sum1)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               0 (s)

  3           6 SETUP_LOOP              30 (to 39)
              9 LOAD_GLOBAL              0 (range)
             12 LOAD_CONST               2 (1000000)
             15 CALL_FUNCTION            1
             18 GET_ITER            
        >>   19 FOR_ITER                16 (to 38)
             22 STORE_FAST               1 (i)

  4          25 LOAD_FAST                0 (s)
             28 LOAD_FAST                1 (i)
             31 INPLACE_ADD         
             32 STORE_FAST               0 (s)
             35 JUMP_ABSOLUTE           19
        >>   38 POP_BLOCK

  5     >>   39 LOAD_FAST                0 (s)
             42 RETURN_VALUE

除了解释器循环慢于C之外,INPLACE_ADD还会创建一个新的整数对象(过去255,CPython将小int对象缓存为单例)。

您可以在Python
mercurial代码存储库中看到C实现,但是它在注释中明确指出:

/* Fast addition by keeping temporary sums in C instead of new Python objects.
   Assumes all inputs are the same type.  If the assumption fails, default
   to the more general routine.
*/


 类似资料:
  • 本文向大家介绍对python中的for循环和range内置函数详解,包括了对python中的for循环和range内置函数详解的使用技巧和注意事项,需要的朋友参考一下 如下所示: 1.for循环和range内置函数配合使用 range函数生成一个从零开始的列表, range(4)表示list:0123 range(1,11,2)表示从1开始到11-1为止步长为2的list:13579 即range

  • 问题内容: 我正在Swift中编写一些性能关键的代码。在实现了我能想到的所有优化并在Instruments中对应用程序进行了性能分析之后,我意识到,绝大多数CPU周期都花在了Floats数组上的执行和操作上。所以,只是为了看看会发生什么,我更换的所有实例,并具有良好的老式循环。令我惊讶的是,循环快得多了! 对此感到有些困惑,我决定执行一些粗略的基准测试。在一个测试中,我执行了一些简单的算术,然后返

  • 本文向大家介绍Python 内置函数globals()和locals()对比详解,包括了Python 内置函数globals()和locals()对比详解的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了Python globals()和locals()对比详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Python的两个内置函数,

  • 我需要关于如何计算while loop打印的数字之和的帮助。我必须用while循环得到1到100的数字,然后把它们计算在一起。比如123。。。98 99 100. 我能得到数字,但不能一起计算。这是我的代码: 我如何让它只打印最后一笔金额?如果我试图欺骗这个等式,它就会挂起。

  • 问题内容: 我正在尝试在循环内创建函数: 问题在于所有功能最终都相同。这三个函数都没有返回0、1和2,而是返回2: 为什么会发生这种情况,我应该怎么做才能获得分别输出0、1和2的3个不同函数? 问题答案: 你在后期绑定方面遇到了问题-每个函数都i尽可能晚地查找(因此,在循环结束后调用时,i将设置为2)。 可以通过强制早期绑定轻松修复:更改为以下形式: 缺省值(右手i输入i=i是参数名的默认值,i左

  • 问题内容: 我有以下代码返回而不是循环内的每个值。 我需要怎么做才能获得循环值? 问题答案: 用 IIFE 封闭 **** 这样的话,价值将被保留,该次迭代的而不是将其设置为时间的最后一个值被称为回