关于深拷贝和浅拷贝

mutable:可变对象.如List Dict set
immutable:不可变对象,如Number String Tuple Frozenset
copy模块:对象拷贝是指在内存中创建新的对象,产生新的内存地址
1.浅拷贝只拷贝外层对象,深拷贝还会递归拷贝内层对象
2.无论是什么拷贝,拷贝可变对象会成为一个新的对象,而不可变对象还是原来那个
3.产生新的对象即内存地址会改变,当顶层对象和子元素全不可变,没有产生新对象,所以不存在被拷贝


浅拷贝(Shallow Copy),拷贝顶层对象,但不会拷贝内部的子元素对象
深拷贝Deep Copy),递归拷贝顶层对象,以及内部的子元素对象

1.顶层是mutable,子元素全是immutable
a=[1,2,'world']
b=copy.copy(a)

print(id(a))
print(id(b))
print([id(itema) for itema in a])
print([id(itemb) for itemb in b])

#拷贝可变对象会产生新对象,内存地址改变,不可变对象不会产生新对象,拷贝对其不影响
a[0]=3
print(a)
print(b)
#改变不可变对象对拷贝的对象不产生影响
输出结果如下:

2069254398600
2069254398664
[140731013096080, 140731013096112, 2069283173688]
[140731013096080, 140731013096112, 2069283173688]
[3, 2, 'world']
[1, 2, 'world']

2.顶层是mutable,子元素部分是immutable

import copy
a=[1,2,['hello','world']]
b=copy.copy(a)

print(id(a))
print(id(b))
输出结果如下:

1337842492104
1337842944904

可以看到内存地址未改变.

以下是我个人所做的一些小总结:

浅拷贝只拷贝顶层对象,即最外层的,外层可变则产生新对象,内层地址改变,反之不改变
浅拷贝对内层对象,即子元素不会拷贝,因此子元素不管是可变还是不可变,内存地址都不会改变

深拷贝会拷贝顶层对象和子元素对象,
当顶层对象可变,拷贝产生新的对象,内存地址改变
因为深拷贝会拷贝子元素,子元素有可变对象时,其子元素内存地址也改变
当顶层对象不可变时,如果子元素全不可变,则其内存地址不会改变
如果子元素有可变对象,由于深度拷贝拷贝子元素,导致子元素内存地址改变,故而拷贝其内存地址也会改变

改变原来的对象不可变子元素对象,拷贝的新对象不会产生改变
改变原来的对象的可变子元素对象
浅拷贝时,拷贝的新对象也会产生改变,因为子元素内存地址没有被改变
深拷贝时,拷贝的对象不会产生改变,因为深拷贝的可变子元素也会被拷贝,成为新的对象,产生了新的内存地址


原文地址:https://www.cnblogs.com/hxwblogs/p/11841253.html