python中深拷贝与浅拷贝

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)

执行过程如下
python中深拷贝与浅拷贝
由图可以看出深拷贝不仅把源数据外层拷贝了,深层数据也进行了拷贝,所以无论源数据外层还是深层如何改变都和深拷贝得到的值无关,互不影响。

浅拷贝

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代码执行过程虚拟图
这个网站可以将你的代码放入查看数据构建以及它的变动等,能帮你更好的理解python执行原理。

上一篇:懒加载和预加载---性能优化


下一篇:property相关补充