为什么要有深浅拷贝
在谈谈深浅拷贝之前,先来说一下变量的等号 (=) 赋值,先看一段代码
>>> a=[1,2,3]
>>> b=a
>>> a,b
([1, 2, 3], [1, 2, 3])
>>> a.append(4)
>>> a,b #可以看到修改了a 后,b也跟着改变了
([1, 2, 3, 4], [1, 2, 3, 4])
对于列表这种可变(mutable)数据类型来说,当执行等号赋值后,他们其实都指向内存中的同一个对象,数据是完全共享的,修改其中一个,另一个必将发生改变
但在某些情况下,我们写程序的时候不希望更改一个变量,另一个也跟着改变,不然就乱了套了, 这时就产生了一种需求:
能不能通过某种手段,将对象的数据复制一份,修改其中一个变量时,另一个不会发生改变?
答案是可以的,这时候深浅拷贝就派上用场了
深浅拷贝是什么,区别在哪里
浅拷贝,其实是分为两个词。“ 拷贝 ” 和“ 浅 ”,
- 拷贝:顾名思义,指的是将对象的数据复制一份
- 浅:指的是,在复制对象数据的时候,只复制第一层数据
下面来看一段代码
>>> a=[1,[1,2,3],3]
>>> b=a[:]
>>> id(a),id(b)
(61635080, 61645128) #可以看到a和b的内存地址已经不同了
>>> a.append(4)
>>> a,b
([1, [1, 2, 3], 3, 4], [1, [1, 2, 3], 3]) #可以看到修改a,b并不会发生改变
从上面的代码可以看出,浅拷贝已经能初步解决那个问题了,修改了a, b并不会发生变化
但是浅拷贝只是复制了第一层数据,第二层或者更高层的数据还是共享的,也就是说上面的问题还没有完全解决
浅拷贝只是复制了第一层的数据,当修改其中一个变量的第二层的数据时,另一个也会跟着改变
可以通过下面的代码来验证一下
>>> a[1].append(4) #通过a[1]来更改了第二层的的数据
>>> a[1],b[1]
([1, 2, 3, 4], [1, 2, 3, 4]) #可以看到修改了其中一个第二层的数据,另一个也会发生改变
这时候深拷贝的作用就出现了,用于祢补浅拷贝的短板,即在复制对象数据的时候,完完整整的复制一份,包括第二层和更高层的数据
深拷贝实现的方式:
>>> import copy
>>> a=[1,[1,2,3],3]
>>> b=copy.deepcopy(a)
而且可以看到修改了其中一个的第二层数据,另一个不会发生改变
>>> a[1].append(4)
>>> a
[1, [1, 2, 3, 4], 3]
>>> b
[1, [1, 2, 3], 3]
深浅拷贝的实现方式
浅拷贝实现的方式有三种
- 切片操作
- 工厂函数
- copy模块中的copy函数
切片操作:
>>> a=[1,[1,2,3],3]
>>> b=a[:]
>>> a,b
([1, [1, 2, 3], 3], [1, [1, 2, 3], 3])
工厂函数:
>>> a=[1,[1,2,3],3]
>>> b=list(a) #与等号赋值的区别,就是多了一个list()函数
>>> a,b
([1, [1, 2, 3], 3], [1, [1, 2, 3], 3])
copy模块中的copy函数:
>>> import copy
>>> a=[1,[1,2,3],3]
>>> b=copy.copy(a)
>>> a,b
([1, [1, 2, 3], 3], [1, [1, 2, 3], 3])
深拷贝的实现方式:
>>> import copy
>>> a=[1,[1,2,3],3]
>>> b=copy.deepcopy(a)
>>> a,b
([1, [1, 2, 3], 3], [1, [1, 2, 3], 3])