python plus等于较慢
我使用python plus等于较慢,python,benchmarking,Python,Benchmarking,我使用timeit运行了一些快速基准测试。重复比较使用\u累加器的两种不同方法 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 __n
timeit运行了一些快速基准测试。重复比较使用\u累加器的两种不同方法
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+
差
注意:在Windows7上使用64位的CPython 3.3.2(使用32位版本的python)这实际上不是一个答案,但它可以帮助您理解python代码中发生了什么。您可以调用这两个函数并获取:
>>> 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\u ADD
和=的BINARY\u ADD
+
我认为+=
是一种就地累加,而执行x=x+y
会在内存中创建一个值为x+y
的新对象,只需重新为其指定名称x
。因此,x=x+y
有两个步骤:在某个寄存器中存储x+y
的值和重新分配xx+=y
还有两个步骤:在某个对象中存储x+y
的值。然后将该值复制到x的位置。将值复制到x
指向的对象位置可能比简单地“重新指定”x
本身的指针值成本更高。但是,嘿,我对Python一无所知,所以这只是我的猜测。运行我得到的相同代码[8.69090794257174,8.65746124451764,9.0220202141028663][9.061213666780041,9.197347861298582,9.04849989044235],这似乎表明+=
更快。@ShashankGupta这取决于对象,因为整数都返回一个新对象。对于列表,+=
是一个就地操作,而另一个返回一个新的列表。@ShashankGupta这取决于这些对象的\uuud\uud\uud\uud\ucode>和\uud\uuuud\uud\uud>方法做什么,对于不可变对象,它们总是返回新对象,对于可变对象,它们的行为可能不同。(整数没有方法。)…@ShashankGupta实际上是不可变的对象,比如int、str,…没有\uu iadd\uuu
方法,所以+=
返回到\uuuu add\uuuu
。是的,它意味着就地添加。如果int
没有\uu iadd\uu
方法,为什么dis
会显示就地添加