📜  Python中的 A += B 赋值谜题(1)

📅  最后修改于: 2023-12-03 15:04:29.984000             🧑  作者: Mango

Python中的 A += B 赋值谜题

在Python中,我们通常使用+=来给一个变量增加值,比如a += 1表示将a加1并把结果赋值给a。但是这个看似简单的赋值操作背后有着不少奥妙,本篇文章就来探讨一下Python中的A+=B的一些神奇之处。

等价于 A = A + B 吗?

我们首先来看看A+=B到底是不是和A = A + B一样的操作。在大多数情况下,这两个操作是等价的,比如:

a = 1
b = 2
a += b
print(a)   # 输出3

a = 1
b = 2
a = a + b
print(a)   # 输出3

这两个代码段看上去没有什么区别,都是把变量a加上变量b的值。但是,如果a是一个可变对象(比如一个列表),情况就不一样了。我们看下面的代码:

a = [1, 2, 3]
b = [4, 5]
a += b
print(a)   # 输出[1, 2, 3, 4, 5]

a = [1, 2, 3]
b = [4, 5]
a = a + b
print(a)   # 输出[1, 2, 3, 4, 5]

两个代码片段看上去依然是等价的,都是把列表a和列表b拼接起来。但是,这里有个细节:a = a + b实际上是先新建一个列表然后再把这个列表赋值给原来的变量a,而a += b则是直接在原来的列表a上面增加元素。

为了更好地理解这个区别,我们可以看看下面的例子:

a = [1, 2, 3]
b = [4, 5]
c = a
a += b
print(c)   # 输出[1, 2, 3, 4, 5]

输出结果竟然是[1, 2, 3, 4, 5]!这是由于列表c和列表a实际上是指向同一个对象的,也就是说,a += b操作直接修改了列表a的值,同时也改变了列表c的值。而a = a + b操作则会新建一个列表来存放合并后的结果,然后再把这个列表赋值给a,此时c并没有改变。

A += B 和 A = A + B 的性能差异

除了上面的赋值行为上的区别外,A += B和A = A + B还有一个显著的区别就是性能表现不同。为了探讨这个问题,我们可以使用Python内置的timeit模块来测试一下。我们让它分别执行1000次A+=B和A=A+B操作,代码如下:

import timeit

a = [1] * 1000
b = [2] * 1000

t1 = timeit.timeit('a += b', globals=globals(), number=1000)
t2 = timeit.timeit('a = a + b', globals=globals(), number=1000)

print('A += B: {:.6f}s'.format(t1))
print('A = A + B: {:.6f}s'.format(t2))

输出结果如下:

A += B: 0.003849s
A = A + B: 0.201633s

你会发现,A += B操作比A = A + B快了很多,约为后者的1/50!这是因为A += B是直接修改a的值,而A = A + B则需要新建一个列表,然后再把这个列表赋值给a。对于小规模的操作来说,两者的表现差异并不明显,但是当数据量变得很大的时候,A += B的优势就凸显出来了。

需要注意的是,这个性能差异只在操作可变对象(比如列表)的时候才会出现,对于不可变对象(比如整数、元组等),两种赋值操作的性能表现是一样的。

总结

A += B和A = A + B看上去很相似,但实际上,它们存在着不少区别。需要注意的是,当A是可变对象的时候,两者的行为可能不同,而且在性能上也有很大的差异。因此,需要在实际编程中根据场景来选择合适的赋值方式。