Python中的赋值号=和+=号不完全一致,在其它很多语言中a += b等价于 a = a + b。对于初学者,90%以上的情况下,Pthon也是如此,例如:
a, b, c = 100, 100, 100
a = a + b
b += c
print(a == b) #True
但是对于可变类型,有时两个符号的运行结果并不等价,例如:
#示例1 一个列表a + 另一个列表c再赋值给自身a
a = [1, 2, 3]
b = a # a is b
c = [4, 5, 6]
a = a + [4, 5, 6] #将改变a的id, a is not b
print(a) #输出[1, 2, 3, 4, 5, 6]
print(b) #[1, 2, 3]
print(a[3] is c[0]) #输出True
print(a[0] is b[0]) #输出True
print(a is b) #输出False
#示例2 一个列表a += 另一个列表c再赋值给自身a
a = [1, 2, 3]
b = a # a is b
c = [4, 5, 6]
a += [4, 5, 6] #不改变a的id,相当于调用列表的extend方法
print(a) #输出[1, 2, 3, 4, 5, 6]
print(b) #输出[1, 2, 3, 4, 5, 6]
print(a[3] is c[0]) #输出True
print(a[0] is b[0]) #输出True
print(a is b) #输出True
总结:
(1) 列表a = 列表a + 列表c后将改变a的id,打印b和a两个列表的元素成员时,结果不同;列表a += 列表c后不改变a的id。两种方式对于a来说从扩充“效果”看,没有任何区别,但对于b 而言却影响重大。
这个例子也告诉我们,在Python中使用a=b这种赋值要慎重,因为Python默认会a变b也变,b变a也变。打个比方,村里有个女孩叫李芳,别人都叫她小芳,即李芳 = 小芳,是一个人。后来小芳去城里,改个名字叫"李丽娜"。你再叫她’'李芳" 她肯定不答应;
但如果以后有一天她回村里,她三姑叫她"小芳",她咋答应呢?
a = ‘李芳’
b = a # b代表‘小芳’
a = 改名为:‘李丽娜’
print(b) # 咋答应?
如果碍于面子她答应了,她当初的改名为:‘李丽娜’ 就类似于+=,因为不管叫啥,人还是一个人;如果她不答应,她当初的改名就类似于+,因为李芳 != 李丽娜,没毛病!
其实Pyhton对于可变类型存在+和+=的区别为什么存在这点差异未知,可能都有道理,就像叫小芳时,她咋答应都或许有道理。女孩由李芳改为李丽娜,对自己来说生活中一般没啥影响,但由于别人叫她"小芳"这个称呼时就会有差异(相当于更改a后,输出b)。
(2) 通过程序中的
c = [4, 5, 6]
a += [4, 5, 6]
print(a[3] is c[0]) #输出True
可知,Python在内存管理时,轻易不将数据重复复制一遍放在内存中。
(3) 列表的+=等价调用了列表的extend方法;而两个列表的+类似于两个集合求并集的操作,是求两个列表所有元素的总体,实际等价创造了一个新的列表。
有同学说这其实是一回事,非也。举个例子,哈尔滨科技大学和哈尔滨电工学院1995年合并为哈尔滨理工大学,这类似于+,虽然两个学校的地还是那几块地,学生还是那些学生,但牌子换了,这种合并至少不会让任何一方感觉难堪;但2000年至2004年间吉林大学先后吞并了包括长春科技大学,长春邮电学院,吉林工业大学,白求恩医科大学以及中国人民解放军军需大学五大高校。虽然从效果来看,跟合并差不多,但明眼人都能看明白咋回事,吞并就类似于+=。
哈尔滨理工大学 = 哈尔滨科技大学 + 哈尔滨电工学院
吉林大学 += [长春科技大学,长春邮电学院,吉林工业大学,白求恩医科大学,中国人民解放军军需大学]
所以看似+和+=都是扩充,但意义不一样。
(4) 补充知识:由于Cpython底层内存管理部分是用C语言实现,所以可能存在黑箱,比如无法直接看一下内存中某个地址中的内容。除了==和is来比较对象外,a is b 为True的必要条件是a和b占用的内存空间一致。
import sys
a = [1, 2, 3]
b = a
a = a + [4, 5, 6]
print(a == b) #输出False
print(a is b) ##输出False
print(sys.getsizeof(a) == sys.getsizeof(b)) #输出False
(5) 其它可变类型有类似特点,比如集合的某些操作。
a ={1, 2, 3}
b = a
a = a & {3, 4, 5} #输出{3}
print(a) #输出{3}
print(b) #输出{1, 2, 3}
print(a is b) #输出False
a ={1, 2, 3}
b = a
a &= {3, 4, 5} #输出{3}
print(a) #输出{3}
print(b) #输出{3}
print(a is b) #输出True