Python深拷贝与浅拷贝用法实例分析
本文实例讲述了Python深拷贝与浅拷贝用法。分享给大家供大家参考,具体如下:
1、对象的赋值
对象的赋值实际上是对象之间的引用:当创建一个对象,然后将这个对象赋值给另外一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用。
当对对象做赋值或者是参数传递或者作为返回值的时候,总是传递原始对象的引用,而不是一个副本。如下所示:
在python中将一个变量赋值给另一个变量,传递的是引用.无论是a的内层变化还是外层变化,b都会发生同样的变化.因为b和a指向了同一个引用.类似于c语言中的同一片内存地址.
#coding=utf-8 a=[1,2,3,['a','b','c']] b=a print('*'*50) print('---b=a---') print('a=%s'%a) print('b=%s'%b) a.append(4) print('---外层a增加了元素4---') print('a=%s'%a) print('b=%s'%b) print('---内层增加了元素"d"---') a[3].append('d') print('a=%s'%a) print('b=%s'%b)
运行结果:
**************************************************
---b=a---
a=[1,2,3,['a','b','c']]
b=[1,2,3,['a','b','c']]
---外层a增加了元素4---
a=[1,2,3,['a','b','c'],4]
b=[1,2,3,['a','b','c'],4]
---内层增加了元素'd'---
a=[1,2,3,['a','b','c','d'],4]
b=[1,2,3,['a','b','c','d'],4]
2、对象的复制
当你想修改一个对象,而且让原始的对象不受影响的时候,那么就需要使用到对象的复制,对象的复制可以通过三种方法实现:
a、使用切片操作进行拷贝--sliceoperation
(注:切片技术应用于所有的序列,包括:列表、字符串、元祖,但切片不能应用于字典。对字典只能使用D.copy()方法或D.deepcopy()方法.)
b、使用工厂函数进行拷贝,list/dir/set--factoryfunction
c、copy.copy()–usecopymodule
在复制的时候,使用的是浅拷贝,复制了对象,但是对象中的元素,依然使用引用。
如下所示:
a=[1,2,3,['a','b','c']]
#coding=utf-8 importcopy #1.切片操作 print('---切片操作---') b=a[:] print('a=%s\tid(a)=%s'%(a,id(a))) print('b=%s\tid(b)=%s'%(b,id(b))) #2.使用工厂函数 print('---使用工厂函数---') c=list(a) print('a=%s\tid(a)=%s'%(a,id(a))) print('c=%s\tid(c)=%s'%(c,id(c))) #3.copy.copy() print('---copy.copy()---') d=copy.copy(a) print('a=%s\tid(a)=%s'%(a,id(a))) print('d=%s\tid(d)=%s'%(d,id(d)))
运行结果:
---切片操作---
a=[1,2,3,['a','b','c']] id(a)=140676047022088
b=[1,2,3,['a','b','c']] id(b)=140676047021320
---使用工厂函数---
a=[1,2,3,['a','b','c']] id(a)=140676047022088
c=[1,2,3,['a','b','c']] id(c)=140676047101640
---copy.copy()---
a=[1,2,3,['a','b','c']] id(a)=140436217635720
d=[1,2,3,['a','b','c']] id(d)=140436217656904
在使用浅拷贝的时候,发现引用的id都是相同的,但是字符串的id却发生了变化,是因为在python中,字符串是不可变的,从而在每次进行修改的时候,都是新建一个对象,从而引用发生了变化.
在不可变类型中,数字和字符串都是不可变类型,从而在每次修改的时候,都是新创建一个对象。
3、模块
核心模块:copy
浅拷贝和深拷贝的操作都可以在copy模块中找到,其实copy模块中只有两个函数可用,copy()进行浅拷贝操作,而deepcopy()进行深拷贝操作.
如下所示:
#coding=utf-8 importcopy a=[1,2,3,['a','b','c']] #浅拷贝拷贝的是外层即顶级对象,对于内层只拷贝引用 #所以在a的外层增加了元素,而c并没有变化.而在a的内层增加元素后,c发生了同样的变化.(回顾b=a) print('*'*50) print('---c=copy.copy(a)---') c=copy.copy(a) print('a=%s'%a) print('c=%s'%c) a.append(4) print('---外层a增加了元素4---') print('a=%s'%a) print('c=%s'%c) print('---内层增加了元素"d"---') a[3].append('d') print('a=%s'%a) print('c=%s'%c) #深拷贝会递归的拷贝所有内容,将所有的内容都独自拷贝了一份. #故而,无论a的外层还是内层发生变化,都不会影响到d. print('*'*50) print('---d=copy.deepcopy(a)---') d=copy.deepcopy(a) print('a=%s'%a) print('d=%s'%d) a.append(5) print('---外层a增加了元素5---') print('a=%s'%a) print('d=%s'%d) print('---内层增加了元素"e"---') a[3].append('e') print('a=%s'%a) print('d=%s'%d)
运行如下:
**************************************************
---c=copy.copy(a)---
a=[1,2,3,['a','b','c']]
c=[1,2,3,['a','b','c']]
---外层a增加了元素4---
a=[1,2,3,['a','b','c'],4]
c=[1,2,3,['a','b','c']]
---内层增加了元素"d"---
a=[1,2,3,['a','b','c','d'],4]
c=[1,2,3,['a','b','c','d']]
**************************************************
---d=copy.deepcopy(a)---
a=[1,2,3,['a','b','c','d'],4]
d=[1,2,3,['a','b','c','d'],4]
---外层a增加了元素5---
a=[1,2,3,['a','b','c','d'],4,5]
d=[1,2,3,['a','b','c','d'],4]
---内层增加了元素"e"---
a=[1,2,3,['a','b','c','d','e'],4,5]
d=[1,2,3,['a','b','c','d'],4]
4、拷贝的警告
第一:非容器类型(比如数字,字符串和其他原子类型的对象,例如代码,类型和xrange对象等)没有拷贝一说,浅拷贝是完全用切片操作来完成的。
第二:如果元组变量只包含原子类型对象,那么深拷贝将不会进行。
#coding=utf-8 importcopy a=(1,2,3) print('*'*50) print('---c=copy.copy(a)---') c=copy.copy(a) print(a,id(a)) print(c,id(c)) print('*'*50) print('---d=copy.deepcopy(a)---') d=copy.deepcopy(a) print(a,id(a)) print(d,id(c))
运行如下:
**************************************************
---c=copy.copy(a)---
(1,2,3)140394676674992
(1,2,3)140394676674992
**************************************************
---d=copy.deepcopy(a)---
(1,2,3)140394676674992
(1,2,3)140394676674992
可见:
对于可变类型来说,深拷贝和浅拷贝是不同的.
而对于不可变类型来说,深拷贝和浅拷贝的结果相同!
更多关于Python相关内容感兴趣的读者可查看本站专题:《Python面向对象程序设计入门与进阶教程》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python编码操作技巧总结》及《Python入门与进阶经典教程》
希望本文所述对大家Python程序设计有所帮助。