这两个运算符很多语言都提供了,好像也没啥好说的,不就是像下面这样子用嘛。
>>> x = 3 >>> y = x+6 >>> y 9 >>> x += 6 >>> x 9
+运算符得到新对象,当然也可以在原对象值的基础上进行增加,例如x = x+6;而+=总是修改原来的对象值。
但如果深入研究的话,情况似乎还是有些出乎意料的,看下面的代码:
>>> x = 3 >>> id(x) 1494131872 >>> x += 6 >>> id(x) 1494132064
其中内置函数id()用来返回一个对象的内存地址。那么上面的代码说明了什么呢?执行+=运算之后,x的内置地址发生了变化。究其原因,在于Python采用的是基于值的自动内存管理模式。变量中不直接存储值,而是存储值的引用,也就是值在内存中的地址。上面代码的执行过程如图所示,在执行x += 6时,首先把原来的3取出来,加上6得到9,把9放到内存中,最后再让x来指向这个新地址。
然而,当+和+=作用于列表时,情况又有所不同。
>>> x = [1, 2, 3] >>> id(x) 1668306802824 >>> x = x + [4] >>> id(x) 1668306565768 >>> x += [5] >>> id(x) 1668306565768
发现了什么?+=作用于列表时居然是原地操作,类似于列表的append()方法。确实是这样的。在类的设计中,特殊方法__iadd__()对应于+=运算符,而+运算符则对应于特殊方法__add__(),有例为证:
>>> class Test: def __init__(self, v): self.__value = [v] def __add__(self, vv): return Test(self.__value[0] + vv) def __iadd__(self, vv): self.__value.append(vv) return self def show(self): return self.__value
>>> t = Test(3) >>> t.show() [3] >>> id(t) 1668306894744 >>> tt = t+6 >>> tt.show() [9] >>> id(tt) 1668306197640 >>> t += 6 >>> t.show() [3, 6] >>> id(t) 1668306894744
既然这样的话,那么列表对象的+=也就是__iadd__()会设计成什么样子,就都是可以理解的了。
最后,如果元组中含有子列表,+=会有一个坑,详见Python编程中一定要注意的那些“坑”(一)