前言:在python中深拷贝和浅拷贝它们的区别是什么,在什么情况下使用浅拷贝好,又在情况下不使用深拷贝可能会出现问题,想要弄明白,我们得从内存下手。
我们先来看下面这段代码:
list_old = [1, 2, 3, 4, 5]
list_new = list_old
list_new[0] = 5
print(list_old)
print(list_new)
# 运行结果
# [5, 2, 3, 4, 5]
# [5, 2, 3, 4, 5]
可以看到列表 list_old 改变的时候,list_new也改变了,那这是为什么呢,我们来看看内存里是如何变化的吧。
list_new = list_old不属于拷贝,仅仅是list_old把列表数据的地址赋值给了变量list_new,所以list_new和list_old中存储的内存地址是相同的,所以在数据发生变化的时候,它们会同时变化。
业务需求就是希望list_new变化,list_old保持不变,这个时候应该如何解决?
浅拷贝:
list_old = [1, 2, 3, 4, 5]
# list_new = list_old.copy()
list_new = [:]
list_new[0] = 5
print(list_old)
print(list_new)
# 运行结果
# [1, 2, 3, 4, 5]
# [5, 2, 3, 4, 5]
如上述代码,我们可以用切片或者python的内置函数copy对列表进行浅拷贝,为什么浅拷贝后就能达到上述的业务需求呢?让我们来看看内存图吧。
如上图所示,浅拷贝创建了一个新的列表对象,当list_new里的数据地址发生改变的时候,并不会影响到list_old。
那如果我把代码改一下,浅拷贝还能完成我们的需求吗?
list_old = [[1, 2], 2, 3, 4, 5]
list_new = list_old[:]
list_new[0][1] = 1
print(list_old)
print(list_new)
# 运行结果
# [[1, 1], 2, 3, 4, 5]
# [[1, 1], 2, 3, 4, 5]
在这段代码中又出现了上面的问题,list_new改变的时候list_old也发生改变,我们来看看内存的变化吧。
我们可以看到,浅拷贝时当列表中的元素有可变类型时,还是会出现上面提到的情况,这个时候我们应该如何解决呢?
深拷贝:
import copy
list_old = [[1, 2], 2, 3, 4, 5]
list_new = copy.deepcopy(list_old)
list_new[0][1] = 1
print(list_old)
print(list_new)
# 运行代码
# [[1, 2], 2, 3, 4, 5]
# [[1, 1], 2, 3, 4, 5]
内存图奉上:
深拷贝拷贝所有层的数据,拷贝后的数据完全独立。
深浅拷贝的对比:
1.深拷贝拷贝所有层的数据,拷贝后的数据完全独立。
优点是修改数据时互不影响,缺点是占用内存较大。
2.浅拷贝拷贝的是第一层数据,共享深层数据。
优点是占用内存较小,缺点是修改深层数据互相影响。
需要拷贝深层数据时使用深拷贝,否则使用浅拷贝。