深拷贝与浅拷贝

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内部引用计数的特性,对于不可变对象,浅拷贝与深拷贝的作用是一致的,就相当于的复制了一个副本,原对象内部的不可变对象的改变,不会影响到复制对象;
  • 浅拷贝的拷贝,其实是拷贝了原始元素的的引用(内存地址),所以拷贝可变对象的时候,原对象内可变对象的对应元素的改变,复制对象的对应元素也会改变;
  • 深拷贝的拷贝,在遇到可变对象的时候,相当于在物理地址上重新开辟了一块区域,存储复制后的可变对象,所以不管副本对象的可变元素如何发生变化,都不会影响到原始对象对应的可变元素.
posted @ 2020-09-22 14:35  郁文  阅读(173)  评论(0)    收藏  举报