Python 深拷贝和浅拷贝的区别
首先深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样
(1)、深拷贝:拷贝了一份与原对象不同地址的对象,修改对象中的任何值,都不会改变深拷贝的对象的值。
(2)、浅拷贝:对原对象值的拷贝,地址仍然指向原对象的地址,原对象的值发生变化,拷贝对象的值也会随着改变。
(3)、深拷贝和浅拷贝需要注意的地方是:可变元素的拷贝
在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的地址是相同的。也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去,而是和原对象里的指向同一个地址。
list1 = [[1, 2], 'feng', 66]
list2 = copy.copy(list1)
# 对象地址不同
print(id(list1)) # 14055210224
print(id(list2)) # 14055208953
# 里面的可变元素地址相同
print(id(list1[0])) # 14055249424
print(id(list2[0])) # 14055249424
下面解释可变类型和不可变类型的嵌套使用:
- 可变类型:
- 浅拷贝和深拷贝只要最外层是可变类型都会生成新的对象
- [] 或者{}, 浅拷贝和深拷贝都会生成新的对象
- [[],[]]列表的嵌套,可变类型嵌套了可变类型,浅拷贝, 只拷贝最外层,会生成新的对象, 内层是引用。深拷贝 外层和内层都会进行拷贝,都是全新的对象, 都有独立的存储空间
- 不可变类型:
- 最外层是不可变类型, 浅拷贝就一定是引用
- ([],[]), copy浅拷贝, 只会拷贝最外层,内层只是引用, 但是最外层是不可变,拷贝之后毫无意义,仅仅是引用关系, deepcopy,从外层到内层都会拷贝,内层是可变,为了达到和原来的数据完全隔离, 会生成全新的对象
- ((),()) 完全不可变, 拷贝了之后如果生成新的数据也无法修改, 所以不管深拷贝还是浅拷贝都是引用
- ((),[]) 外层不可变,但是内层有一个是可变, copy依然是引用, deepcopy,会生成新的对象,内层的不可变类型是引用, 可变类型会生成新的对象