is VS ==
简单来说,==
比较的是值大小,is
比较的是内存地址,总的来说,is运算符的速度大于==运算符,这是在于is运算符没办法重载,而运行==运算符时,程序会先去搜索__eq__
函数,如果没有重载,就会直接比较大小,由于python很多内置的函数都重载了__eq__
函数
值得注意的是,对于整型数字来说,a is b为True的结论,只适用于-5到256之间,比如:
1 | 257 a = |
原因在于,出于性能考虑,python内部会维持一个-5到256的数组,起到一个缓存的作用。每次你去创建一个-5到256范围的整型数字时,python会去这个数组中取值,而不是去创建一个新的内存。
浅拷贝与深拷贝
浅拷贝:是指重新分配一块内存,创建一个新的对象,里面的元素是对原对象中子对象的引用。如果原对象中元素是不可变类型,不会产生影响,如果是可变类型,会带来新对象的改变。
深拷贝:指重新分配一块新的内存地址,创建一个新的对象和新的元素,和原对象没有任何关联。
注意,浅拷贝带来的变化只针对原对象的子对象是可变类型数据,例如嵌套列表
1 | 1, 2], 3] a = [[ |
1 | 1, 2], (3, 4)] a = [[ |
而深拷贝不会受到任何影响
1 | from copy import deepcopy |
深拷贝也不是完美的,如果被拷贝对象是自身,程序有可能会陷入无限循环
1 | 1] x = [ |
x为一个无限嵌套的列表,深拷贝的时候,程序并没有报stack overflow
的现象,这是在于深拷贝函数内部维护这一个字典,记录已经拷贝对象和ID,拷贝过程中,如果字典里存储了将要拷贝对象,会直接将字典中内容返回
而在使用==比较深拷贝之后的无限嵌套列表时,会抛出异常RecursionError: maximum recursion depth exceeded in comparison
,这是在于列表中==会去遍历每个值的大小再去比较,而列表时无限嵌套的,所以会抛出异常
1 | import copy |