Python中的复制操作及copy模块中的浅拷贝与深拷贝方法
程序中常常需要复制一个对象,按思路应该是这样的
a=[1,2,3] b=a #[1,2,3] printb
已经复制好了,但是现在得改变一下第一个元素的值把它改成5
b[0]=5 #[5,2,3] printb #[5,2,3] printa
我改变了b的第一个元素的值,但是a的值也改变了,这是因为python中的=是引用.a和b指向的是相同的列表,所以改变列表会出现以上的结果.
解决方法是切片操作
a=[1,2,3] b=a[:] b[0]=4 #[1,2,3] #[4,2,3] printa printb
但是在嵌套列表的时候呢,试一试
a=[[1,2,3],4,5] b=a[:] b[1]=0 #[[1,2,3],4,5] #[[1,2,3],0,5] printa printb
恩!没什么问题,在试一试嵌套列表元素
a=[[1,2,3],4,5] b=a[:] b[0][0]=5 #[[5,2,3],4,5] #[[5,2,3],4,5] printa printb b=a[:]
a的值还是改变了,切片复制只对该对象进行拷贝不会对子元素进行拷贝
copy模块
copy模块用于对象的拷贝操作。该模块非常简单,只提供了两个主要的方法:copy.copy与copy.deepcopy,分别表示浅复制与深复制。什么是浅复制,什么是深复制,网上有一卡车一卡车的资料,这里不作详细介绍。复制操作只对复合对象有效。用简单的例子来分别介绍这两个方法。
浅复制只复制对象本身,没有复制该对象所引用的对象。
#coding=gbk importcopy l1=[1,2,[3,4]] l2=copy.copy(l1) printl1 printl2 l2[2][0]=50 printl1 printl2
结果:
[1,2,[3,4]] [1,2,[3,4]] [1,2,[50,4]] [1,2,[50,4]]
同样的代码,使用深复制,结果就不一样:
importcopy l1=[1,2,[3,4]] l2=copy.deepcopy(l1) printl1 printl2 l2[2][0]=50 printl1 printl2
结果:
[1,2,[3,4]] [1,2,[3,4]] [1,2,[3,4]] [1,2,[50,4]]
改变copy的默认行为
在定义类的时候,通过定义__copy__和__deepcopy__方法,可以改变copy的默认行为。下面是一个简单的例子:
classCopyObj(object): def__repr__(self): return"CopyObj" def__copy__(self): return"Hello" obj=CopyObj() obj1=copy.copy(obj) printobj printobj1
结果:
CopyObj Hello