python深浅拷贝

白昼怎懂夜的黑 提交于 2020-04-08 08:30:10

int, float,str, tuple都是不可变对象,

dic,set,list属于可变对象。可变,是指内存中的值,不是指地址。

1 浅拷贝

拷贝规则:

  1. 如果被拷贝对象是不可变对象,则不会生成新的对象
  2. 如果被拷贝对象是可变对象,则会生成新的对象,但是只会对可变对象最外层进行拷贝
import copy


a = 4343.23
b = copy.copy(a)

print(id(a))
print(id(b))

  

上面的代码对一个float类型的数据进行了浅拷贝,根据规则,不会生成新的对象,因此a,b两个变量的内存地址是相同的。

下面是一个可变对象的拷贝示例

import copy

a = [1, [1]]
b = copy.copy(a)

print(id(a), id(b))
print(id(a[1]), id(b[1]))

  

程序输出结果是

4739120648 4387519880
4739160904 4739160904

  

a和b的内存地址是不相同的,说明生成了一个新的数据,但由于是浅拷贝,因此列表里的元素并不进行拷贝,只对最外层进行了拷贝。

通过对内存的观察,我们可以更清楚了解浅拷贝的过程,下图是浅拷贝之前的内存示意图


浅拷贝发生之后,内存变成如下图所示


为了便于识别,我特地将代表引用的线条加粗并加上颜色来区分,通过对比浅拷贝前后的示意图,你可以看到,仅仅生成了一个新的对象,地址是4350709128。

a[1], b[1] 的数据类型是列表,是可变对象,他们的内存地址相同,因此,对b[1]的操作,将会影响到a[1]

import copy

a = [1, [1]]
b = copy.copy(a)

b[1].append(2)
print(a)

  

程序输出结果

[1, [1, 2]]

  

明明只是对变量b进行了操作,却影响到了a,这绝对是个安全隐患,因此进行浅拷贝时要非常小心,除非你清楚的知道自己在做什么,可能带来哪些影响,否则就不要进行浅拷贝,现在不缺内存,别玩火。

2. 深拷贝

拷贝规则:

  1. 如果被拷贝对象是不可变对象,深拷贝不会生成新对象,因为被拷贝对象是不可变的,继续用原来的那个,不会产生什么坏的影响
  2. 如果被拷贝对象是可变对象,那么会彻底的创建出一个和被拷贝对象一模一样的新对象
import copy

a = [1, [1]]
b = copy.deepcopy(a)

print(id(a), id(b))
print(id(a[1]), id(b[1]))

  

程序输出结果

4739124744 4350819720
4739165000 4739236104

  

为了清晰的理解深拷贝的作用,还是放上拷贝前后的内存对比图

深拷贝前


深拷贝之后


和浅拷贝相比,最大的不同在于,新生成了一个列表[1],内存地址和a[1]不一样,深拷贝之后,对b的任何操作,都不会影响到a,虽然多耗费了一些内存,但是更加安全。
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!