Python:使用copy模块深拷贝对象
2016-09-10 22:55
459 查看
Python语言中有深拷贝和浅拷贝的概念,那什么是深拷贝,浅拷贝呢?
浅拷贝(shallow copy):构造一个新的复合对象并将从原对象中发现的引用(也就是地址,而不是地址所指向的内容)插入该对象中。浅拷贝的实现方法有很多种,如工厂函数、切片操作、copy模块中的copy操作。 深拷贝(deep copy):也构造一个新的复合对象,但是遇到引用会继续递归拷贝其所指向的内容,也就是说他会针对引用所指向的对象继续执行拷贝,因此产生的对象不受其它对象操作的影响。深拷贝的实现需要依赖copy模块的deepcopy()操作先看下面例子吧,定义了一个Pizza类和Order类,分别反应Pizza信息和订单信息
order2 customer name:zhangcustomer2 order information:customer name:LiPizza name:MushroomPizza size:12Pizza price:30Pizza name:seafoodPizza size:9Pizza price:40Pizza name:fruitPizza size:9Pizza price:30可以说还是满足客户2的要求的,修改客户2订单信息后再来看看客户1订单信息,
140206506600080140206506602064140206506652560140206507110552 customer2的订单是由copy.copy(customer1)获得,把customer2的pizzalist的id打印出来与customer1的pizzalist同时打印出来,代码如下:
140206506600080
140206506602064
140206506652560
140206507110552
--------------------------
140206506600080
140206506602064
140206506652560
140206507110552
发现是一样的,这是由于copy.copy()得到的是一个浅拷贝,它仅仅拷贝了对象的地址而不对对应地址所指的具体内容进行拷贝。
包含引用的数据结构中,浅拷贝并不能进行彻底拷贝,当存在字典、列表等可变对象时,它仅仅拷贝了其引用地址,并没有拷贝对应地址的内容。要解决这个问题就需要使用深拷贝,深拷贝不仅拷贝了引用也拷贝了引用所指向的对象(也就是内容),因此深拷贝得到的对象与原对象是相互独立的。
如果将上面程序改为customer2 = copy.deepcopy(customer1)来实现就不会出现这样的问题。
下面简单介绍一些copy模块的一些知识:
copy模块的主要对外接口就是copy()和deepcopy()。
在定义类的时候,通过定义__copy__和__deepcopy__方法,可以改变copy的默认行为。下面是一个简单的例子:
CopyObj
copy
CopyObj
-----------------
Copyobj
Copyobj
deep copy
浅拷贝(shallow copy):构造一个新的复合对象并将从原对象中发现的引用(也就是地址,而不是地址所指向的内容)插入该对象中。浅拷贝的实现方法有很多种,如工厂函数、切片操作、copy模块中的copy操作。 深拷贝(deep copy):也构造一个新的复合对象,但是遇到引用会继续递归拷贝其所指向的内容,也就是说他会针对引用所指向的对象继续执行拷贝,因此产生的对象不受其它对象操作的影响。深拷贝的实现需要依赖copy模块的deepcopy()操作先看下面例子吧,定义了一个Pizza类和Order类,分别反应Pizza信息和订单信息
#coding=utf-8 import copy class Pizza(object): """ Pizza类 """ def __init__(self,name,size,price): self.name = name self.size = size self.price = price def showPizzaInfo(self): print "".join(('Pizza name:',self.name)) print "".join(("Pizza size:",str(self.size))) print "".join(('Pizza price:',str(self.price))) #字符串的拼接尽量使用join()函数,不要使用+号,因为前者效率更高,而且更Pythonnic def getPizzaInfo(self): return self.name,self.size,self.price def changename(self,name): self.name = name def changesize(self,size): self.size = size def changeprice(self,price): self.price = price class Order(object): """ 订单类 """ def __init__(self,name): self.customername = name self.pizzalist = [] self.pizzalist.append(Pizza("Mushroom",12,30)) def ordermore(self,pizza): self.pizzalist.append(pizza) def changename(self,name): self.customername = name def getorderdetail(self): print "".join(('customer name:',self.customername)) for one in self.pizzalist: one.showPizzaInfo() def getPizza(self,number): return self.pizzalist[number] customer1 = Order("zhang") customer1.ordermore(Pizza("seafood",9,40)) customer1.ordermore(Pizza("fruit",12,35)) print "customer1 order infomation:" customer1.getorderdetail() print "--------------------"上面代码描述的意思是客户1下了一个订单,并且把具体订单打印出来的场景。运行结果如下:customer1 order infomation:customer name:zhangPizza name:MushroomPizza size:12Pizza price:30Pizza name:seafoodPizza size:9Pizza price:40Pizza name:fruitPizza size:12Pizza price:35--------------------假设客户2也想跟客户1下一样的订单,只是改变了水果Pizza的尺寸,那么价格也应该作相应的修改。于是想到拷贝客户1的订单信息并做一定的修改,代码如下:
customer2 = copy.copy(customer1) print "".join(["order2 customer name:",customer2.customername]) customer2.changename("Li") customer2.getPizza(2).changesize(9) customer2.getPizza(2).changeprice(30) print "customer2 order information:" customer2.getorderdetail() print "----------------------"输出结果如下:
order2 customer name:zhangcustomer2 order information:customer name:LiPizza name:MushroomPizza size:12Pizza price:30Pizza name:seafoodPizza size:9Pizza price:40Pizza name:fruitPizza size:9Pizza price:30可以说还是满足客户2的要求的,修改客户2订单信息后再来看看客户1订单信息,
print "customer1 order infomation:" customer1.getorderdetail() print "----------------------"结果如下:customer1 order infomation:customer name:zhangPizza name:MushroomPizza size:12Pizza price:30Pizza name:seafoodPizza size:9Pizza price:40Pizza name:fruitPizza size:9Pizza price:30----------------------客户1订单信息除了客户姓名外,其它和客户2订单信息居然一样了。如果这真是一个生成用的系统,必将会影响客户的满意度,因为客户1没有要求修改订单信息呀。这怎么回事呢? customer1 中的pizzalist是由Pizza对象组成的列表,其中存放的实际是对一个个具体Pizza对象的引用,在内存中就是一个具体的位置,可以打印出它们的id
print id(customer1.pizzalist[0]) print id(customer1.pizzalist[1]) print id(customer1.pizzalist[2]) print id(customer1.pizzalist)结果如下:
140206506600080140206506602064140206506652560140206507110552 customer2的订单是由copy.copy(customer1)获得,把customer2的pizzalist的id打印出来与customer1的pizzalist同时打印出来,代码如下:
print id(customer1.pizzalist[0]) print id(customer1.pizzalist[1]) print id(customer1.pizzalist[2]) print id(customer1.pizzalist)打印结果如下
print "--------------------------"
print id(customer2.pizzalist[0])
print id(customer2.pizzalist[1])
print id(customer2.pizzalist[2])
print id(customer2.pizzalist)
140206506600080
140206506602064
140206506652560
140206507110552
--------------------------
140206506600080
140206506602064
140206506652560
140206507110552
发现是一样的,这是由于copy.copy()得到的是一个浅拷贝,它仅仅拷贝了对象的地址而不对对应地址所指的具体内容进行拷贝。
包含引用的数据结构中,浅拷贝并不能进行彻底拷贝,当存在字典、列表等可变对象时,它仅仅拷贝了其引用地址,并没有拷贝对应地址的内容。要解决这个问题就需要使用深拷贝,深拷贝不仅拷贝了引用也拷贝了引用所指向的对象(也就是内容),因此深拷贝得到的对象与原对象是相互独立的。
如果将上面程序改为customer2 = copy.deepcopy(customer1)来实现就不会出现这样的问题。
下面简单介绍一些copy模块的一些知识:
copy模块的主要对外接口就是copy()和deepcopy()。
在定义类的时候,通过定义__copy__和__deepcopy__方法,可以改变copy的默认行为。下面是一个简单的例子:
#coding=utf-8 import copy class CopyObj(object): def __repr__(self): return "CopyObj" def __copy__(self): return "copy" obj = CopyObj() obj1 = copy.copy(obj) obj2 = copy.deepcopy(obj) print obj print obj1 print obj2 print "-----------------" class Copyobj(object): def __repr__(self): return "Copyobj" def __deepcopy__(self,meno=None): return "deep copy" a = Copyobj() b = copy.copy(a) c = copy.deepcopy(a) print a print b print c输出结果如下:
CopyObj
copy
CopyObj
-----------------
Copyobj
Copyobj
deep copy
相关文章推荐
- python 包和模块 等于号(==)和is的区别与联系 对象的拷贝(copy)
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python中模块使用及面向对象介绍
- python之copy模块与深拷贝、浅拷贝
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python中的数据对象持久化存储模块pickle的使用示例
- Python拷贝对象(浅拷贝copy与深拷贝deepcopy)
- Python中的复制操作及copy模块中的浅拷贝与深拷贝方法
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)
- python中datetime模块中datetime对象的使用方法
- Python 拷贝对象(深拷贝deepcopy与浅拷贝copy)