- 论坛徽章:
- 0
|
转:Yao
Python中的增强赋值
从2.0开始,Python支持一组额外的赋值语句,称为增强赋值语句(Augmented assignment statements),比如“-=”,“+=”,“/=”等等。所谓“增强”是与通常写法比较而言,学过其它类似C,Java,C#等语言的同学都知道,“a += b”其实就等于"a = a + b",只是写法上有所简化。但在Python里,事情却没那么简单,里面猫腻还真不少……
为了方便查看内存的变化,需要用到“id”这个方法,它会返回python对象的整型标识符,其实在多数情况下这个“标识符”就是对象的内存地址,使用help(id),可以看到说明如下:- 1 id(...)
- 2 id(object) -> integer
- 3
- 4 Return the identity of an object. This is guaranteed to be unique among
- 5 simultaneously existing objects. (Hint: it's the object's memory address.)
复制代码 后面的代码使用str(hex(id(...)))来打印出变量的地址。
先来看demo:- 01 # -*- coding: utf-8 -*-
- 02
- 03 lst = [1,2,3,4]
- 04
- 05 print("Before: ", str(hex(id(lst))))
- 06
- 07 lst2 = lst
- 08 print("List2 : ",str(hex(id(lst2))))
- 09
- 10 lst = lst + [5,6] #普通赋值语句
- 11 #lst += [5,6] #增强赋值语句
- 12
- 13 print("After : ", str(hex(id(lst))))
- 14
- 15 print( lst is lst2 )
复制代码 在我机子上,输出为(注意:运行时具体数值可能会不同):- 1 ('Before: ', '0xb786c5acL')
- 2 ('List2 : ', '0xb786c5acL')
- 3 ('After : ', '0xb788174cL')
- 4 False
复制代码 可以看到,lst2 与lst地址相同,也就是说他们指向了同一个对象,就是所谓的"共享引用",这与预期相同。
第10行代码,lst与另外一个列表([5,6])做"+“运算时,首先会生成一个新的列表对象,然后lst指向这个新对象,这个过程中lst参与了两次运算(一次是参与新对象生成,第二次是指向新对象),这也在我们期望之中。
接下来,注释掉第10行代码,并取消第11行的注释,再次运行程序,结果如下:- 1 ('Before: ', '0xb77355acL')
- 2 ('List2 : ', '0xb77355acL')
- 3 ('After : ', '0xb77355acL')
- 4 True
复制代码 地址没变?!什么情况?原来在使用增强赋值语句时,Python会在可能的情况下执行原地(in-place)修改,比如,上面的代码,python会在lst原来的内存空间的后面“扩展”一些内存,用来存放[5,6],这样,lst其实只参与了一次运算,而且没有发生额外的内存复制,所以要比普通赋值语句执行更快!
在demo的第9行和第16行添加下面的代码,可以查看列表内每个元素的地址,来验证前面的结论。- 1 for item in lst:
- 2 print("Item%d: %x"%(item,id(item)))
复制代码 可以看到地址是连续的:- 01 ('Before: ', '0xb77585acL')
- 02 ('List2 : ', '0xb77585acL')
- 03 Item1: 9d7bd68
- 04 Item2: 9d7bd5c
- 05 Item3: 9d7bd50
- 06 Item4: 9d7bd44
- 07 ('After : ', '0xb77585acL')
- 08 True
- 09 Item1: 9d7bd68
- 10 Item2: 9d7bd5c
- 11 Item3: 9d7bd50
- 12 Item4: 9d7bd44
- 13 Item5: 9d7bd38
- 14 Item6: 9d7bd2c
复制代码 总的来说,写python代码时尽可能的多使用增强赋值语,因为它比普通赋值语句少了一次运算,而且在可能的情况下会执行原处(in-place)修改,执行起来也更快一些,也可以少打几个字
留个小问题:
上面加粗的“可能的情况”这几个字是什么意思,什么情况下会失败呢?可以把demo里的list改为integer,然后看看结果,然后思考list和integer这两种类型有什么不同?为什么会造成这种结果? Enjoy it! |
|