Python中深拷贝与浅拷贝详解

所有Python对象都有三个属性:身份、类型、值

name='a'
id(name)		#id-身份唯一标识
type(name)	#对象类型

1.可变对象

列表、字典、集合,指可变对象的值可变,身份不变

2.不可变对象

数字、字符串、元组对象身份和值都不可变。新创建对象被关联到原来变量名,旧对象被丢弃,垃圾回收器会在适当时机回收这些对象

3.引用

Python程序中每个对象都会在内存区域中申请一块空间来保存,该对象在内存中所在位置地址被称为引用。开发程序时所定义的变量名实际是对象地址引用,引用是内存中的一个数字地址编号,使用对象时只要知道该对象的地址,就可操作这个对象,但因为数字地址不方便在开发时使用和记忆,所以使用变量名形式来代替对象数字地址。Python中变量就是地址的一种表示形式,并不新开辟存储空间

就像IP地址,访问网站时实际都是通过IP地址确定主机,而IP地址不方便记忆,所以使用域名代替IP地址,使用域名访问网站时被解析成IP地址使用

age=18
id(age)
Out: 1730306752
id(18)
Out: 1730306752

赋值的本质是让多个变量同时引用同一个对象的地址

4.浅拷贝

只拷贝父对象,不拷贝对象内部中的子对象

不可变对象:

不可变对象只在修改时才会在内存中开辟新空间,而拷贝实际上是让多个对象同时指向一个引用,和对象赋值没区别

import copy
a=10
b=copy.copy(a)

id(a)
Out:1730306496
id(b)
Out:1730306496

可变对象:

可变对象拷贝会在内存中开辟一个新空间来保存拷贝数据。当再改变之前对象时,对拷贝之后的对象没有任何影响

import copy
l1=[1,2,3]
l2=copy.copy(l1)		#l2=l1[:] 利用切片完成浅拷贝

id(l1)
Out:1916631742088

id(l2)
Out:1916636282952

l1[0]=11			#数字为不可变对象

id(l1)
Out:1916631742088
id(l2)
Out:1916636282952

l1		#[11,2,3]
l2		#[1,2,3]





l1=[1,2,3]
l2=l1

id(l1)
Out: 1916633584008
id(l2)
Out: 1916633584008

l1[0]=11

id(l1)
Out: 1916633584008
id(l2)
Out: 1916633584008

print(l1,l2)			#[11,2,3] [11,2,3]

复杂对象在拷贝时并没有解决数据在传递之后的数据改变问题。原因是copy函数在拷贝对象时只是将指定对象的所有引用拷贝一份,如果这些引用当中包含一个可变对象(如列表),那么数据还是会被改变。这种拷贝方式称为浅拷贝

a=[1,2]
l1=[3,4,a]
l2=copy.copy(l1)
id(l1)
Out:1916631704520
id(l2)
Out:1916631713736

a[0]=11
id(l1)
Out:1916631704520
id(l2)
Out:1916631713736

l1
Out:[3,4,[11,2]]
l2
Out:[3,4,[11,2]]

5.深拷贝

区别于浅拷贝只拷贝顶层引用,深拷贝会逐层进行拷贝,直到拷贝的所有引用都是不可变引用为止(拷贝对象及其子对象)

import copy
a=[1,2]
l1=[3,4,a]
l2=copy.deepcopy(l1)

id(l1)
Out:1916632194312
id(l2)
Out:1916634281416

a[0]=11
id(l1)
Out:1916632194312
id(l2)
Out:1916634281416

l1
Out:[3,4,[11,2]]

l2
Out:[3,4,[1,2]]

6.浅拷贝优势

1.时间角度:浅拷贝花费时间更少

2.空间角度:浅拷贝花费内存更少

3.效率角度:浅拷贝只拷贝顶层数据,一般情况下比深拷贝效率高

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章