深浅拷贝
在python中对象的赋值其实就是对象的引用
- 浅拷贝 shadow copy
仅仅只拷贝对象自身,内部元素引用的其他对象只拷贝一个引用。 - 深拷贝 deep copy
外围和内部元素都拷贝了对象本身。而不是引用。因此深拷贝产生的副本可以随意修改,而不用担心会影响原始值。
# shadow copy
c = [[1,2,3],'a',4]
d = c.copy()
print(d) # 此时d与c输出结果相同
d[1] = 'b'
print(d) # 此时只更改了d中‘a’ 为‘b’;没有影响到c的值
d[0][1] = 'h'
print(c)
print(d) #此时c,d都被更改!
值得注意的是:深层拷贝并非完完全全递归查找所有对象,因为一旦对象引用了自身,完全递归可能会导致无限循环。一个对象被拷贝了,python会对该对象做个标记,如果还有其他需要拷贝的对象引用着该对象,它们的拷贝其实是指向同一份拷贝;
import copy
a=[1,2,3]
b=[a,a]
c=copy.deepcopy(b)
id(b[0])==id(c[0]) # False
id(b[0])==id(b[1]) # True
c[0].append('p')
应用范围:
对于不可变类型的对象,深浅拷贝效果都是一样。(字符串、元组、数字)
对于可变类型的对象,效果如下
a = [1,2,3] # ‘=’浅拷贝 b = a print(a) print(b) print(id(a)) print(id(b)) # copy 浅拷贝 b = a.copy() print(a) print(b) print(id(a)) print(id(b)) # deep copy 深拷贝 b = a.deepcopy() print(a) print(b) print(id(a)) print(id(b))
结果:
总结:
- 深浅拷贝都是对源对象的复制,占用不同的内存空间;
- 不可变类型的对象,深浅拷贝的区别毫无影响,最后的值和地址都是相同的;
- 对于可变类型:
= 浅拷贝:值相同,地址相同
copy 浅拷贝:值相同,地址不同
deep copy:值相同,地址不同