十.Python中深拷贝、浅拷贝
1.浅拷贝
浅拷贝,简单的理解,就是只拷贝了引用,但没有拷贝其内容。
举个例子,旅店小于的房间号302, 小于告诉了小明自己的房间号(假定知道房间号同时就有了进入房间的钥匙和权利),小于在房间中添加一把椅子,小明进入房间就可以看到。
小于忘记了自己房间号,但是通过小明还可以进入这个房间。
代码示例
In [1]: d1 = [1, 2, 3] #小于的房间302
In [2]: d2 = d1 # 告知给小明
In [3]: print(id(d1),id(d2)) # 两人记忆的房间号302
140110307510784 140110307510784
In [6]: d1.append(4) # 小于给302房间添加一把椅子
In [7]: d1 # 小于添加的,当然可以看到
Out[7]: [1, 2, 3, 4]
In [8]: d2 # 小明进入的也是302,自然也可以看到小于加的椅子
Out[8]: [1, 2, 3, 4]
In [9]: del d1 # 小于忘记了302房间
In [10]: d2 # 小明记得,
Out[10]: [1, 2, 3, 4]
In [11]: d1 # 当然Python中有垃圾回收机制
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-11-2d3a24957153> in <module>()
----> 1 d1
NameError: name 'd1' is not defined
这是一个很简单的浅拷贝,那看接下来的示例
In [17]: d3 = [1, 2]
In [18]: d4 = ['a', 'b']
In [19]: d5 = [d3, d4]
In [20]: d6 = d5
In [21]: import copy
In [22]: d7 = copy.copy(d5)
In [23]: print(id(d5), id(d6), id(d7)) # 发现d7的id与其他两个不一样
140110298615888 140110298615888 140110317120880
In [24]: d5.append('x')
In [25]: d5
Out[25]: [[1, 2], ['a', 'b'], 'x']
In [26]: d6
Out[26]: [[1, 2], ['a', 'b'], 'x']
In [27]: d7
Out[27]: [[1, 2], ['a', 'b']] # d7没有变化
In [28]: d3.append(3)
In [29]: d5
Out[29]: [[1, 2, 3], ['a', 'b'], 'x']
In [30]: d6
Out[30]: [[1, 2, 3], ['a', 'b'], 'x']
In [31]: d7
Out[31]: [[1, 2, 3], ['a', 'b']] # d7同样有变化
上面的示例说明copy.copy只是复制最顶层的列表,但里面存放是依然相同的引用。
2.深拷贝
与浅拷贝对应的就是深拷贝,深拷贝是对于一个对象所有层次的拷贝。
代码示例
In [32]: import copy
In [33]: p1 = ['a', 'b']
In [34]: p2 = copy.deepcopy(p1)
In [35]: print(id(p1), id(p2))
140110298618608 140110298305312
In [36]: p1.append(3)
In [37]: print(p1, p2)
['a', 'b', 3] ['a', 'b']
In [38]:
In [38]: b1 = ['a', 'b']
In [39]: b2 = [1, 2]
In [40]: c1 = [b1, b2]
In [41]: c2 = copy.deepcopy(c1)
In [42]: b1.append('c')
In [43]: c1
Out[43]: [['a', 'b', 'c'], [1, 2]]
In [44]: c2
Out[44]: [['a', 'b'], [1, 2]]
从结果可以看到深拷贝与浅拷贝的不同
3.不可变数据类型
copy.copy对于不可变类型,不会发生拷贝,它只是指向,但copy.deepcopy依然是拷贝
代码示例
In [45]: import copy
In [46]: t1 = ('a', 'b')
In [47]: t2 = copy.copy(t1)
In [48]: print(id(t1), id(t2))
140110307485168 140110307485168
In [49]: t3 = copy.deepcopy(t1)
In [50]: print(id(t1), id(t3))
140110307485168 140110307485168