python---深拷贝(deep copy)、浅拷贝(shallow copy)
1、对象的比较
== : 比如a==b ,比较的是a和b指向的值是否相等
is : 比较的是对象的身份表示是否相等,是否指向同一个内存地址
2、id值
整数-5 ~ 256 :python内部对整型-5 ~ 256 维持了一个数组,每次创建这样的整型数字时,python返回的都是数组对应的引用
超过以上范围的引用,就单独开辟一块内存空间了,每次创建,其id值也会不一样
浅拷贝: 重新分配一块内存,创建新对象,新对象中的元素是对原对象元素的引用。所以,如果原对象中的元素是可变的,比如是一个列表,其添加或者删除元素等操作会在两个对象中引起共变。
l1 = [[1, 2], (30, 40)]
l2 = list(l1)
l1.append(100)
l1[0].append(3)
l1
[[1, 2, 3], (30, 40), 100]
l2
[[1, 2, 3], (30, 40)]
l1[1] += (50, 60)
l1
[[1, 2, 3], (30, 40, 50, 60), 100]
l2
[[1, 2, 3], (30, 40)]
可变序列,可以通过切片完成浅拷贝
深拷贝:重新分配一块内存,创建新的对象,新对象中的元素是递归复制原对象中的元素(不是仅复制引用),所以,新对象和原对象没有任何关联,绝对不会引起共变。
深拷贝的缺陷:如果拷贝的元素对象,存在指向自身的引用,就会陷入死循环
解决办法:深度拷贝 维护了一个字典,记录已经拷贝过的对象及其id, 在拷贝过程中,如果字典已经存在的对象,会直接返回
python提供了相应包实现拷贝:(需要导入import copy)
浅拷贝 copy.copy()
深拷贝 copy.deepcopy()
元组:
t1 = (1, 2, 3)
t2 = tuple(t1)
t3 = t1[:]
t1 == t2 # 返回True ,t1和t2中值相同
t1 is t2 #返回True , t1和t2指向了相同的引用
t1 is t3 # t1和t3指向了相同的引用
总结:
一、赋值:
在 Python 中,对象的赋值就是简单的对象引用,这点和 C++不同
二、浅拷贝(shallow copy):
浅拷贝会创建新对象,其内容非原对象本身的引用,而是原对象内第一层对象的引用。浅拷贝有三种形式:切片操作、工厂函数、copy 模块中的 copy 函数。
三、深拷贝(deep copy):
深拷贝只有一种形式,copy 模块中的 deepcopy()函数。深拷贝和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。因此,它的时间和空间开销要高。
四、拷贝的注意点:
1、对于非容器类型,如数字、字符,以及其他的“原子”类型,没有拷贝一说,产生的都是原对象的引用。
比如 l1 = [999,1000,1001]
l2 = copy.copy(l1)
l2 is l1 # False
l2[0] is l1[0] # True
2、如果元组变量值包含原子类型对象,即使采用了深拷贝,也只能得到浅拷贝。