*拷贝python对象(浅拷贝、深拷贝)
浅拷贝——
对一个“对象”进行浅拷贝其实就是新创建了一个类型跟原对象一样,内容是原来对象元素的引用,
换句话说:这个拷贝的对象本身是新的,但是内容不是。
什么情况下是浅拷贝:
1、完全切片 [:]
2、工厂函数 比如:list(),dict()
3、使用copy模块的copy函数
演示浅拷贝特性
#!/usr/bin/env python3 #-*- coding:utf-8 -*- count = ['name',['saveings',100]] wife = count[:] husband = list(count) def view_list(*a): print(a) def view_id(*a): for i in a: print(id(i)) view_list(wife,husband) view_id(count,wife,husband) wife[0] = 'Nichole' husband[0] = 'Alben' wife[1][1] = 50 view_list(wife,husband)
解析:
定义1个count列表,其中两个元素,‘name’、‘[’saveings’,100]
列表wife 通过完全切片拷贝而来
列表husband 通过工厂拷贝而来
第一次调用函数:view_list,结果
(['name', ['saveings', 100]], ['name', ['saveings', 100]])
第一次调用函数:view_id,结果
34359816
34360056
34360976
从id的值上看,这三个列表都是不同的对象。
把"wife","husband"列表中的第一个值重定义:
wife[0] = 'Nichole'
husband[0] = 'Alben'
把wife列表第二个元素(列表)中的第二个元素改为100(意味着老婆取款50)
第二次运行函数:view_list与view_id的结果:
(['Nichole', ['saveings', 50]], ['Alben', ['saveings', 50]])
34228744
34228984
34229904
我们会发现,"wife"和"husband"两个列表第二个元素中的第二个元素都改变了!
why?
因为是浅拷贝!
但是为什么在修改"husband"列表[0]值的时候,没有同时修改"wife"呢?
因为"wife","husband"两个列表的第一个元素是字符串(不可变对象)
但是第二个元素时列表,是可变对象。
所以在拷贝的时候,字符串被显式的拷贝了,并且创建了新的字符串对象,而列表只是把它的引用复制了一下,
所以改变第二个对象的时候是两个引用会同时变化。
验证:
改变前
print([id(x) for x in wife])
print([id(x) for x in husband])
结果:
[4006400, 37112288]
[4006400, 37112288]
改变后:
[34288320, 34294240]
[34288384, 34294240]
这样就很明显了,两个列表第一个元素“字符串”改变后,id值是不同的,但是第二个元素“列表”的id值是相同的。
深拷贝:
通过copy()函数的deepcopy()功能。
修改上段代码:
#!/usr/bin/env python3 #-*- coding:utf-8 -*- import copy count = ['name',['saveings',100]] wife = count husband = copy.deepcopy(count) def view_id(*a): for i in a: print(id(i)) def view_list(*a): print(a) wife[0] = 'Nichole' husband[0] = 'Alben' wife[1][1] = 50 view_list(wife,husband) print([id(x) for x in wife]) print([id(x) for x in husband])
结果:
(['Nichole', ['saveings', 50]], ['Alben', ['saveings', 100]])
[34484928, 38064296]
[34484992, 38065256]
深拷贝是创建两个对象,所有id()结果两个元素对象的值都不同!
关于深拷贝的注意点:
第一,非容器类型(数字、字符串、其他‘原子’类型)没有被拷贝一说,例如元组,对他深拷贝是无效的。