python中深拷贝与浅拷贝
要搞清楚深拷贝和浅拷贝,我们必须要先清楚两个概念:可变对象,不可变对象。
可变对象和不可变对象
可变对象
所谓可变对象,字面上理解就是可以改变的,那么可以改变什么呢?例如,列表、字典和集合,他们里面的值可以随时进行改变,长度也是可变的。
可变对象在增删改的时候始终都还是最开始的那个可变对象,地址始终不会变。
# 初始列表
list_a = [1, 2, 3]
print(list_a, id(list_a))
# 删除
list_a.clear()
print(list_a, id(list_a))
# 增加
list_a.append(5)
print(list_a, id(list_a))
# 修改
list_a[0] = 999
print(list_a, id(list_a))
执行之后结果如下
[1, 2, 3] 2192497398280
[] 2192497398280
[5] 2192497398280
[999] 2192497398280
由此可以看出,可变对象无论如何去变动它的值,都是始终操作的同一个对象,地址是相同的。
不可变对象
而不可变对象则本身不能够去进行增删改的行为的,一旦去做那就是重新创建了一个对象,并非原本的对象。
# 初始字符串和一个数字
i = 5
s = 'hello'
print(i, id(i))
print(s, id(s))
# 增加
i = i + 1
s = s + ' world'
print(i, id(i))
print(s, id(s))
执行后结果如下
5 140733792484544
hello 1932519655280
6 140733792484576
hello world 1932549001968
可以很明显看到在进行了改动之后,已经不是原来的那个对象了。
深拷贝和浅拷贝
这时候再来说深拷贝和浅拷贝。其实就是对象和引用的关系。变量值我们可以看作是一个对象,变量名则是对这个对象的引用。
可变对象只要不重新进行赋值,而是去做增删改的操作。那么它的引用就始终是指向它的。
不可变对象只要进行变动的操作,那么就等于重新创建了一个对象,把引用重新指向了这个新的对象。
深拷贝
import copy
original_list = [19, 97, [1, 2, 3], 1, 9, 123]
print(original_list)
deep_copy_list = copy.deepcopy(original_list)
original_list[2].append(12)
print(original_list)
print(deep_copy_list)
执行过程如下
由图可以看出深拷贝不仅把源数据外层拷贝了,深层数据也进行了拷贝,所以无论源数据外层还是深层如何改变都和深拷贝得到的值无关,互不影响。
浅拷贝
import copy
original_list = [19, 97, [1, 2, 3], 1, 9, 123]
print(original_list)
copy_list = copy.copy(original_list)
original_list[2].append(12)
print(original_list)
print(copy_list)
执行过程如下
由此图可以看出,浅拷贝只是将源数据外层单独拷贝了一份,但是深层的并没有拷贝,还是和源数据指向同一个对象的,一旦其发生改变,则两个都会随着改变。
链接:python代码执行过程虚拟图
这个网站可以将你的代码放入查看数据构建以及它的变动等,能帮你更好的理解python执行原理。