深拷贝
深拷贝就是在每个层次都对可变对象进行拷贝,浅拷贝只对最外层可变对象进行拷贝。
我们先来看看赋值的情况即b = a,如下图所示:(灵魂画手终于上场···)
示意图a与b指向同一个对象,我们通过代码验证其正确性:
交互式Python代码:
>>> a = [1, 2, [3, 4]]
>>> b = a
>>> id(b) == id(a)
True
>>> id(a[0]) == id(b[0])
True
>>> id(a[1]) == id(b[1])
True
>>> id(a[2]) == id(b[2])
True
>>> id(a[2][0]) == id(b[2][0])
True
>>> id(a[2][1]) == id(b[2][1])
True
再来看看浅拷贝的情况,先上图:
上图中为b = a[:]示意图,b为a的浅拷贝,浅拷贝会将最外层可变对象进行拷贝,下面进行代码验证:
交互式Python代码:
>>> a = [1, 2, [3, 4]]
>>> b = a[:]
>>> id(b) == id(a)
False
>>> id(a[0]) == id(b[0])
True
>>> id(a[1]) == id(b[1])
True
>>> id(a[2]) == id(a[2])
True
>>> id(a[2][0]) == id(b[2][0])
True
>>> id(a[2][1]) == id(b[2][1])
True
最后来看看深拷贝,深拷贝我们需要用到copy库的deepcopy,示意图如下:
接下来进行代码验证:
交互式Python代码:
>>> from copy import deepcopy
>>>
>>> a = [1, 2, [3, 4]]
>>> b = deepcopy(a)
>>> id(a) == id(b)
False
>>> id(a[0]) == id(b[0])
True
>>> id(a[1]) == id(a[1])
True
>>> id(a[2]) == id(b[2])
False
>>> id(a[2][0]) == id(b[2][0])
True
>>> id(a[2][1]) == id(b[2][1])
True
因此当实参为可变对象且其中含有多层嵌套的可变对象时,如果我们不想因为我们的粗心让函数更改实参,那么我们就应该使用深拷贝,看代码:
交互式Python代码:
>>> a = [1, 2, [3, 4]]
>>> def func(List):
List.append('hello world')
List[0] = 'shawn'
List[2][0] = 'simon'
List[2][1] = 199
return List
>>> from copy import deepcopy
>>> b = func(deepcopy(a))
>>> a
[1, 2, [3, 4]]
>>> b
['shawn', 2, ['simon', 199], 'hello world']
Note: Python中的深拷贝和浅拷贝只是针对可变对象而言,而对于不可变对象无所谓深拷贝还是浅拷贝,因为对于不可变对象两种拷贝和变量之间赋值没什么两样。
交互式Python代码:
>>> from copy import deepcopy
>>>
>>> a = 'hello world'
>>> b = deepcopy(a)
>>> c = a
>>> id(a) == id(b) == id(c)
True