浅拷贝(copy.copy())是对一个对象的顶层(外层)拷贝,只是拷贝了引用,并没有拷贝内容。
深拷贝(copy.deepcopy())是对一个对象深层的拷贝,不仅外层拷贝,内层也拷贝,保证了数据的独立性,有备份的效果。
变量的赋值:事实上是地址的引用,它并不像C语言中为一个变量赋值就会该变量重新开辟一块新的内存空间,在python中变量的赋值实际上两者指向了同一块内存地址:
变量的赋值就是地址的引用,因此也算是浅拷贝。
要想深入理解深拷贝和浅拷贝,需要分拷贝的数据类型而定,当然了还有特殊情况,下面一一介绍:
先说一下数据类型,可变数据类型:列表、字典、集合 。不可变数据类型:数字、字符串、元组
1.对于可变数据类型来说,浅拷贝只是拷贝外层,里面该指向谁还指向谁,而深拷贝则是完全拷贝:
案例一:
下图比较对于不可变数据类型深、浅拷贝的差异:
列表alist1中数字1,2,3为不可变数据类型,但里面嵌套的列表为可变数据类型,浅拷贝只是拷贝了里面嵌套的列表的引用,当修改其中的值时,浅拷贝出来的引用也随之改变,但是深拷贝则是直接将内容拷贝过来,因此值不会发生改变。可以简单理解为:
变量赋值:旧瓶装旧醋,浅拷贝:旧瓶装新醋(开辟了一块新的内存地址,但里面存放的是源数据的引用),深拷贝:新瓶装新醋(开辟了一块新的内存地址,但里面存的不是源数据的引用了,而是源数据一模一样的副本,相当于备份。)
2.对于纯的不可变数据类型来说,无论是深拷贝还是浅拷贝,都只是指向同一个地址。
案例二:
因为元组是不可变类型数据,即使拷贝了也不能实现增删改查,因此它不会去拷贝,而是直接指向了。
3.特殊情况:如果不可变数据类型中还包含可变数据类型,则浅拷贝是指向,深拷贝则是完全拷贝。
案例三:
4.最后:列表的切片和字典的copy()方法都属于浅拷贝。
来个题目小试一下:
m=[1,2,[3]]
n=m[:]
n[1]=4
n[2][0]=5
print(m)
可以自行验证,答案打印出的结果为:
[1,2,[5]]