微信号:Python_xiaowu

介绍:清华出版社《Python程序设计》系列教材作者董付国的Python小屋.介绍Python基础语法知识、标准库、扩展库知识,探讨Python在各领域的应用.

Python运算符+与+=的那些事

2017-01-12 15:41 董付国

这两个运算符很多语言都提供了,好像也没啥好说的,不就是像下面这样子用嘛。

>>> 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编程中一定要注意的那些“坑”(一)

 
Python小屋 更多文章 Python导入标准库和扩展库对象的几种方式 Python扩展库安装工具pip的高级用法 Python编写的数字拼图游戏(含爬山算法人机对战功能) 详解Python使用模拟退火算法求解列表“最大值” Python使用递归法对整数进行因数分解
猜您喜欢 【技术贴慎入】尹海宁:详解SAP预测分析技术、模型与应用 基于gatling&jenkins快速打造性能测试平台 [原]python画词云图(电商评论数数据) 赛尔原创 | 真实信息发现任务及方法介绍 [译]Quora是如何进行答案排名的