【Python】Python 使用copy模块深拷贝对象

Python 使用copy模块深拷贝对象

浅拷W和深拷贝的概念:

浅拷贝(shallow copy ):构造一个新的复合对象并将从原对象中发现的引用插人该对象 中。浅拷贝的实现方式有多种,如工厂函数数、切片操作、copy模块中WCoPy操作等。

深拷贝(deepCoPy):也构造一个新的复合对象,但是遇到引用会继续递归拷贝其所指 向的具体内容,也就是说它会针对引用所指向的对象继续执行拷贝, 因此产生的对象 不受其他引用对象操作的影响^深拷贝的实现需要依赖copy模块的 deepcopy() 操作。

下面我们通过一段简单的程序来说明浅拷贝和深拷贝之间的区别。

import copy
class Pizza():
def init (self,name,size,price):
self.name=name
self.size=size
self.price=price
def getPizzaInfo(self):
return self.name,self.size,self.price
def showPizzaInfo(self):
print(“Pizza name :”+self.name)
print(“Pizza size:”+self.size)
print(“Pizza price:”+self.price)
def changeSize(self,size):
self.size=size
def changePrice(self,price):
self.price=price
class Order():
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(“customer name:”+self.customername)
for i in self.pizzaList:
i.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 information:”)
customer1.getorderdetail()
customer1 order information:
customer name:zhang
Pizza name :mushroom
Pizza size:12
Pizza price:30
Pizza name :seafood
Pizza size:9
Pizza price:40
Pizza name :fruit
Pizza size:12
Pizza price:35
程序描述的是客户在Pizza店里下了一个订单,并将具体的订单信息打印出来的场景。 运行输出结果如下:

customer2=copy.copy(customer1)
print(“order2 customer name”)
customer2.customername
customer2.changeName(“li”)
customer2.getPizza(2).changeSize(“9”)
customer2.getPizza(2).changePrice(“30”)
print(“customer 2 order information:”)
customer2.getorderdetail()
order2 customer name
customer 2 order information:
customer name:li
Pizza name :mushroom
Pizza size:12
Pizza price:30
Pizza name :seafood
Pizza size:9
Pizza price:40
Pizza name :fruit
Pizza size:9
Pizza price:30
假设现在客户2也想下一个跟客户1 —样的订单,只是要将预定的水果披萨的尺寸和价 格进行相应的修改。于是服务员拷贝了客户]的订单信息并做了一定的修改,代码如下;

在修改完客户2的订单信息之后,现在我们再来检査一下客户1的订单信息:

print(“customer1 order information:”)
customer1.getorderdetail()
customer1 order information:
customer name:zhang
Pizza name :mushroom
Pizza size:12
Pizza price:30
Pizza name :seafood
Pizza size:9
Pizza price:40
Pizza name :fruit
Pizza size:9
Pizza price:30
你会发现客户丨的订单内容除了客户姓名外,其他的居然和客户2的订单具体内容一样了。

这是怎么回事呢?客户丨根本没要求修改订单的内容f这样的结果必定会直接影响到客 户满意度。问题出现在哪里?这是我们本节要重点讨论的内容。我们先来分析客户1和客户 2订单内容的关系图,如图所示。 image1

customerl中的pizzaList是一个由Pizza对象组成的列表,其中存放的实际是对一个个 具体Pizza对象的引用,在内存中就是一个具体的地址,可以通过査看id得到相关信息a

print(id (customer1 .pizzaList [0]))
print(id (customer1 .pizzaList [1]))
print(id (customer1 .pizzaList [2]))
print(id (customer1.pizzaList))
139711528292304
139711528291856
139711528292248
139711528345224
customer2的订单通过copy.copy(customerl)获得,通过id函数査看customer2中 pizzaList的具体Pizza对象你会发现它们和customerl中的输出是一样的(读者可以自行验 证)。这是由于通过copy.copy()得到的customer2是customerl的一个浅拷贝,它仅仅拷贝了 pizzalist里面对象的地址而不对对应地址所指向的具体内容(即具体的pizza)进行拷贝,因 此cust〇mer2中的pizzaList所指向的具体内容是和customer!:中一样的,如图4-1所示。所 以对pizza fruit的修改直接影响了 customerl的订单内容。实际上在包含引用的数据结构中, 浅拷瓜并不能进行彻底的拷贝,当存在列表、字典等不可变对象的时候,它仅仅拷贝其引用 地址。要解决上述问题需要用到深拷贝,深拷贝不仅拷贝引用也拷贝引用所指向的对象,因 此深拷贝得到的对象和原对象是相互独立的。 上面的例子充分展示了浅拷贝和深拷贝之间的差异,在实际应用中要特別注意这两者之 间的区别。实际上Python coj>y模块提供了与浅拷贝和深拷贝对应的两种方法的实现,通过 名字便可以轻易进行区分,模块在拷贝出现异常的时候会拋出copy.error。

copy.copy(x) ; Return a shallow copy of x.
copy, deepcopy exception copy- error : Raised for module specific errors.
实际上,上面的程序应该将customer2=copy.copy(customer])改为copy.deepcopy()来实 现(请读者自行验证)。

你可能感兴趣的:(Python,技术研发,python,开发语言)