深浅拷贝
之前的理解
浅拷贝
浅拷贝是拷贝引用,指向同样的内存对象
In [18]: a=1
In [19]: b=a
In [20]: id(1)
Out[20]: 11915608
In [21]: id(a)
Out[21]: 11915608
In [22]: id(b)
Out[22]: 11915608
有些情况下我们将一个变量赋值给另外一个变量,是希望两个变量都独立拥有数据,两个变量时没有任何关系的,但是默认情况下的结果事与愿违
In [23]: a={'a': 1}
In [24]: b=a
In [25]: a['a']=2
In [26]: b
Out[26]: {'a': 2}
解决个问题的方法就是使用深拷贝
深拷贝
深拷贝不像浅拷贝那样只拷贝引用,深拷贝会将引用的对象真正的拷贝一份,并在内存中新开辟一块区域存放它
copy.deepcopy()
Python中使用copy模块中的deepcopy方法可以实现深拷贝
In [27]: import copy
In [28]: a={'a': 1}
In [29]: b=copy.deepcopy(a)
In [30]: a['a']=2
In [31]: b
Out[31]: {'a': 1}
这样上面浅拷贝的问题就解决了,因为这时候a、b引用不是一个对象
In [32]: id(a)
Out[32]: 140115200758680
In [33]: id(b)
Out[33]: 140115201127880
新Get到的姿势
copy.deepcopy()真的是所有情况都时深拷贝么?
先看几个好玩的例子
In [34]: import copy
In [35]: a=1
In [36]: b=copy.deepcopy(a)
In [37]: id(a)
Out[37]: 11915608
In [38]: id(b)
Out[38]: 11915608
In [39]: a='LotusChing'
In [40]: b=copy.deepcopy(a)
In [41]: id(a)
Out[41]: 140115216435408
In [42]: id(b)
Out[42]: 140115216435408
In [43]: a=('1', '2', '3')
In [44]: b=copy.deepcopy(a)
In [45]: id(a)
Out[45]: 140115220239376
In [46]: id(b)
Out[46]: 140115220239376
上面几个例子可以看到她们都是使用了浅拷贝,因为引用的都是同样的内存对象,由此得出了一个概念
当copy.deepcopy()拷贝不可变类型的对象时,例如常量、元组等都会使用浅拷贝
copy.copy() 和copy.deepcopy()区别?
乍一看copy.copy()
也是深拷贝
In [47]: a={'a':1}
In [48]: b=copy.copy(a)
In [49]: a['a']=2
In [50]: b
Out[50]: {'a': 1}
其实不然~
In [51]: l1=[1,2,3]
In [52]: l2=[4,5,6]
In [53]: a=[l1, l2]
In [54]: b=copy.copy(a)
In [55]: id(a)
Out[55]: 140115200801896
In [56]: id(b)
Out[56]: 140115200824528
In [57]: l1.append(4)
In [58]: a
Out[58]: [[1, 2, 3, 4], [4, 5, 6]]
In [59]: b
Out[59]: [[1, 2, 3, 4], [4, 5, 6]]
首先,有两个list,l1、l2,a引用了l1、l2
然后,通过copy.copy()拷贝了a,通过id可以看到a、b此时引用的是不同的对象,但是当我们append l1时,b也跟着发生了变化
原因是因为copy.copy()模块时只对第一层实行深度拷贝,至于第一层拷贝里引用的对象,她也直接偷懒使用了引用,而copy.deepcopy()不同,哪怕有多层她也一定会完整的拷贝出新的对象
In [60]: l1=[1,2,3]
In [61]: l2=[1,2,3]
In [62]: a=[l1, l2]
In [63]: b=copy.deepcopy(a)
In [64]: l1.append(4)
In [65]: a
Out[65]: [[1, 2, 3, 4], [1, 2, 3]]
In [66]: b
Out[66]: [[1, 2, 3], [1, 2, 3]]