python加上等于慢

时间:2013-09-15 17:23:06

标签: python benchmarking

我使用timeit.repeat运行了一些快速基准测试,比较了使用_accumulator_的两种不同方法。

def testAccumPlusEqual():
    x = 0
    for i in range(100):
        x += 1
    return x

def testAccumEqualPlus():
    x = 0
    for i in range(100):
        x = x + 1
    return x

timeit.repeat的实施是:

if __name__ == '__main__':
    import timeit
    print(timeit.repeat("testAccumPlusEqual()",
                    setup="from __main__ import testAccumPlusEqual"))
    print(timeit.repeat("testAccumEqualPlus()",
                    setup="from __main__ import testAccumEqualPlus"))

结果如下:

>>> 
[8.824021608811469, 8.80440620087051, 8.791231916848997]
[8.101681307351758, 8.143080002052649, 8.181129610882778]

当然,在宏观方案中,这个时间差异可能并不明显,但如果大规模使用,可能会导致速度减慢。所以我想我真的在问:

从我看过的所有地方来看,事实上的标准是积累+=,但是情况应该如此吗?

为什么+=的效果会比x=x+差?

注意:在Windows 7 64bit上使用CPython 3.3.2(使用32位版本的python)

1 个答案:

答案 0 :(得分:2)

这实际上不是一个答案,但它可以帮助您了解Python代码中发生的事情。您可以在两个函数上调用dis并获取:

>>> import dis
>>> dis.dis(testAccumEqualPlus)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               0 (x)

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

  4          25 LOAD_FAST                0 (x)
             28 LOAD_CONST               3 (1)
             31 BINARY_ADD          
             32 STORE_FAST               0 (x)
             35 JUMP_ABSOLUTE           19
        >>   38 POP_BLOCK           

  5     >>   39 LOAD_FAST                0 (x)
             42 RETURN_VALUE        
>>> dis.dis(testAccumPlusEqual)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               0 (x)

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

  4          25 LOAD_FAST                0 (x)
             28 LOAD_CONST               3 (1)
             31 INPLACE_ADD         
             32 STORE_FAST               0 (x)
             35 JUMP_ABSOLUTE           19
        >>   38 POP_BLOCK           

  5     >>   39 LOAD_FAST                0 (x)
             42 RETURN_VALUE

如您所见,唯一的区别是INPLACE_ADD的{​​{1}}和+=的{​​{1}}