深拷贝与浅拷贝
Python中的引用计数
Python对不可变对象的内存管理方式是引用计数.
因此我们在谈论拷贝的时候,其主要的特点都是基于可变对象的,如dict,list
示例代码如下:
import copy
a = 'zhangsan'
b=a
c = copy.copy(a)
d = copy.deepcopy(a)
id(a)
Out[7]: 2955462045168
id(b) # 赋值
Out[8]: 2955462045168
id(c) # 浅拷贝
Out[9]: 2955462045168
id(d) # 深拷贝
Out[10]: 2955462045168
由上可知,Python在操作不可变对象的时候,引用计数的方式管理他们,Python不会对值相同的不可变对象申请单独的内存空间,只会记录他的引用次数.
Python中的浅拷贝
Python 中的浅拷贝和赋值如下示例:
import copy
a = ['shangsan','lisi','wangwu']
b=a
c=copy.copy(a)
id (a)
Out[19]: 2008271035976
id (b)
Out[20]: 2008271035976
id (c)
Out[21]: 2008276003208
在Python中的赋值指向原有的对象,而浅拷贝则会创建一个新的对象,但是该对象还是指向原来的内存位置,通过遍历对象的元素的内存地址可发现内存地址一致
a = ['shangsan','lisi','wangwu',["copy-原始"]]
b = copy.copy(a)
[id(_) for _ in a]
Out[42]: [2008276015728, 2008276016688, 2008276015472, 2008275895944]
[id(_) for _ in b]
Out[43]: [2008276015728, 2008276016688, 2008276015472, 2008275895944]
a[3][0] = "copy-修改后"
a[2]="tom"
a
Out[46]: ['shangsan', 'lisi', 'tom', ['copy-修改后']]
b
Out[47]: ['shangsan', 'lisi', 'wangwu', ['copy-修改后']]
浅拷贝之后,操作原对象中的可变元素时,拷贝的副本元素会发生对应的变化,操作原对象中的不可变元素的时候,拷贝的副本元素不会发生变化.
Python 中的深拷贝
Python中的深拷贝如下:
a = ['shangsan','lisi','wangwu',["copy-原始"]]
b = copy.deepcopy(a)
a
Out[50]: ['shangsan', 'lisi', 'wangwu', ['copy-原始']]
b
Out[51]: ['shangsan', 'lisi', 'wangwu', ['copy-原始']]
[id(_) for _ in a]
Out[52]: [2008276015728, 2008276016688, 2008276015472, 2008275894664]
[id(_) for _ in b]
Out[53]: [2008276015728, 2008276016688, 2008276015472, 2008276046984]
a[3][0] = "copy-修改后"
a[2]="tom"
a
Out[58]: ['shangsan', 'lisi', 'tom', ['copy-修改后']]
b
Out[59]: ['shangsan', 'lisi', 'wangwu', ['copy-原始']]
[id(_) for _ in a]
Out[56]: [2008276015728, 2008276016688, 2008275925040, 2008275894664]
[id(_) for _ in b]
Out[57]: [2008276015728, 2008276016688, 2008276015472, 2008276046984]
在Python的深拷贝过程中,对原始对象的不可变元素进行操作后,不影响拷贝副本,且操作原始对象的可变元素的可变元素的时候,也不会影响到可变元素的内存地址.
结论
- 由于Python内部引用计数的特性,对于不可变对象,浅拷贝与深拷贝的作用是一致的,就相当于的复制了一个副本,原对象内部的不可变对象的改变,不会影响到复制对象;
- 浅拷贝的拷贝,其实是拷贝了原始元素的的引用(内存地址),所以拷贝可变对象的时候,原对象内可变对象的对应元素的改变,复制对象的对应元素也会改变;
- 深拷贝的拷贝,在遇到可变对象的时候,相当于在物理地址上重新开辟了一块区域,存储复制后的可变对象,所以不管副本对象的可变元素如何发生变化,都不会影响到原始对象对应的可变元素.

浙公网安备 33010602011771号