我的Python学习笔记(二):浅拷贝和深拷贝
2018-01-08 00:00
344 查看
摘要: Python的浅拷贝和深拷贝的理解
在Python中,对象赋值,拷贝(浅拷贝和深拷贝)之间是有差异的,我们通过下列代码来介绍其区别
如下例所示,将test赋值给copytest后,test和copytest的id值相同,test和copytest指向的是同一个list,所以当test的值改变时,copytest的值也相应改变
copy模块中包含如下两个方法:
copy.copy(x)方法返回x的浅拷贝,copy.deepcopy(x)方法返回x的深拷贝
我们来理解下浅拷贝和深拷贝的区别:
浅拷贝和深拷贝的区别只与复合对象有关系(复合对象就是对象中包含其他对象,例如list和其他实例类)
浅拷贝构造了一个新的复合对象,然后(尽可能)把原来的对象引用直接插入到新对象中
深拷贝构造了一个新的复合对象,然后递归的将原对象中的内容进行复制,并插入新对象
test和copytest的id值不同,但copytest并没有将copy内的值重新拷贝一份,而是直接指向copy内的值。
当执行test[0] = "changetest”时,test[0]重新指向字符串”changetest”,而copttest[0]仍然指向字符串”test”。
当执行test[2].append("css”)时,更改了test[2]指向的list中的值,而test和copytest都指向此list,所以copytest也相应改变了
注:字典的浅拷贝可以使用dict.copy(),list的浅拷贝可以使用slice截取整个list,例如:copied_list = original_list[:]
test和copytest的id值不同,copytest将test中的list重新拷贝了一份,并指向重新拷贝的list
当执行test[0] = "changetest”时,test[0]重新指向字符串”changetest”,而copttest[0]仍然指向字符串”test”。
当执行test[2].append("css”)时,更改了test[2]指向的list的值,但copytest和test指向的并不是同一个list,所以copytest并不受影响
注:深拷贝存在两个问题:一个是递归拷贝可能导致递归循环,另一个是深拷贝会拷贝所有的对象,而有些可以复用的对象也会被重复拷贝,导致拷贝过多的情况
在Python中,对象赋值,拷贝(浅拷贝和深拷贝)之间是有差异的,我们通过下列代码来介绍其区别
一、对象赋值
对象赋值不会复制对象,它只会复制一个对象引用,不会开辟新的内存空间如下例所示,将test赋值给copytest后,test和copytest的id值相同,test和copytest指向的是同一个list,所以当test的值改变时,copytest的值也相应改变
test = ["test", 18, ["python","java"]] copytest = test print(test) # ['test', 18, ['python', 'java']] print(copytest) # ['test', 18, ['python', 'java']] print(id(test)) # 4559314816 print(id(copytest)) # 4559314816 test[0] = "changetest" test[2].append("css") print(test) # ['changetest', 18, ['python', 'java', 'css']] print(copytest) # ['changetest', 18, ['python', 'java', 'css']] print(id(test)) # 4559314816 print(id(copytest)) # 4559314816
二、拷贝
对于复合对象,如果有时我们不想因为其中一个对象改变而改变另外一个对象的值,我们可以使用Python的copy模块。copy模块中包含如下两个方法:
copy.copy(x)方法返回x的浅拷贝,copy.deepcopy(x)方法返回x的深拷贝
我们来理解下浅拷贝和深拷贝的区别:
浅拷贝和深拷贝的区别只与复合对象有关系(复合对象就是对象中包含其他对象,例如list和其他实例类)
浅拷贝构造了一个新的复合对象,然后(尽可能)把原来的对象引用直接插入到新对象中
深拷贝构造了一个新的复合对象,然后递归的将原对象中的内容进行复制,并插入新对象
1、浅拷贝
在下例中,浅拷贝会为copytest开辟新的内存空间,但copytest中的对象仍然是test中的对象引用,不会对其中的对象进行复制import copy test = ["test", 18, ["python","java"]] copytest = copy.copy(test) print(test) # ['test', 18, ['python', 'java']] print(copytest) # ['test', 18, ['python', 'java']] print(id(test)) # 4484571008 print(id(copytest)) # 4484611320 print [id(x) for x in test] # [4484554208, 140582137648080, 4484569424] print [id(x) for x in copytest] # [4484554208, 140582137648080, 4484569424] test[0] = "changetest" test[2].append("css") print(test) # ['changetest', 18, ['python', 'java', 'css']] print(copytest) # ['test', 18, ['python', 'java', 'css']] print(id(test)) # 4484571008 print(id(copytest)) # 4484611320 print [id(x) for x in test] # [4484554352, 140582137648080, 4484569424] print [id(x) for x in copytest] # [4484554208, 140582137648080, 4484569424]
test和copytest的id值不同,但copytest并没有将copy内的值重新拷贝一份,而是直接指向copy内的值。
当执行test[0] = "changetest”时,test[0]重新指向字符串”changetest”,而copttest[0]仍然指向字符串”test”。
当执行test[2].append("css”)时,更改了test[2]指向的list中的值,而test和copytest都指向此list,所以copytest也相应改变了
注:字典的浅拷贝可以使用dict.copy(),list的浅拷贝可以使用slice截取整个list,例如:copied_list = original_list[:]
2、深拷贝
在下例中,深拷贝会为copytest开辟新的内存空间,并将test中的复合对象进行拷贝,并将其引用赋值给新copytestimport copy test = ["test", 18, ["python","java"]] copytest = copy.deepcopy(test) print(test) # ['test', 18, ['python', 'java']] print(copytest) # ['test', 18, ['python', 'java']] print(id(test)) # 4476972928 print(id(copytest)) # 4477013240 print [id(x) for x in test] # [4476956224, 140706592084752, 4476971344] print [id(x) for x in copytest] # [4476956224, 140706592084752, 4477013312] test[0] = "changetest" test[2].append("css") print(test) # ['changetest', 18, ['python', 'java', 'css']] print(copytest) # ['test', 18, ['python', 'java']] print(id(test)) # 4476972928 print(id(copytest)) # 4477013240 print [id(x) for x in test] # [4476956512, 140706592084752, 4476971344] print [id(x) for x in copytest] # [4476956224, 140706592084752, 4477013312]
test和copytest的id值不同,copytest将test中的list重新拷贝了一份,并指向重新拷贝的list
当执行test[0] = "changetest”时,test[0]重新指向字符串”changetest”,而copttest[0]仍然指向字符串”test”。
当执行test[2].append("css”)时,更改了test[2]指向的list的值,但copytest和test指向的并不是同一个list,所以copytest并不受影响
注:深拷贝存在两个问题:一个是递归拷贝可能导致递归循环,另一个是深拷贝会拷贝所有的对象,而有些可以复用的对象也会被重复拷贝,导致拷贝过多的情况
相关文章推荐
- Python学习笔记_浅拷贝,深拷贝
- 流畅的python学习笔记第八章:深拷贝,浅拷贝,可变参数
- Python学习笔记【引用VS拷贝】
- Python学习笔记——可变类型&不可变类型&深拷贝&浅拷贝
- Python学习笔记(5):赋值、浅拷贝、深拷贝
- Python学习笔记之拷贝
- python学习笔记-Day02 -第三部分 浅拷贝和深拷贝
- python学习笔记:深拷贝,浅拷贝
- python学习笔记:深浅拷贝的使用和原理
- Python学习笔记——深拷贝与浅拷贝
- python学习笔记(五)深拷贝浅拷贝,文件和目录
- Python学习笔记摘要(一)类型 字符串 函数 列表 深浅拷贝
- 我的Python学习笔记(二):浅拷贝和深拷贝
- python学习笔记——浅拷贝与深拷贝
- python学习笔记七:浅拷贝深拷贝
- Python学习笔记08
- [Python学习笔记]3——强大的.format
- Python学习笔记:字符串
- Python学习笔记 --- 序列化Serialize 和 反序列化Deserialize
- Python学习笔记(18.01.14)