欢迎来到我的博客园

python学习[第十篇] 数据类型之 浅拷贝深拷贝

python学习[第十篇] 数据类型之 浅拷贝深拷贝

浅拷贝 当创建一个对象,然后把它赋值给另一个对象时,python并没有拷贝这个对象,而是拷贝了这个对象的引用。

深拷贝 创建一个新的容器对象包含原有对象元素(引用)全新拷贝的引用。

 

实例:创建三个对象,person为原型,hubby及wifey为 person的拷贝(浅拷贝)

>>> saving = ['saving',100]
>>> id(saving)
40240552
>>> person = ['name',saving]
>>> hubby = person[:]
>>> wifey = list(person)
>>> hubby,wifey
(['name', ['saving', 100]], ['name', ['saving', 100]])
>>> [ id(x) for x in [person,hubby,wifey] ]
[40260872, 40261032, 40260672]
>>> [ id(x) for x in person ]
[31597728, 40240552]
>>> [ id(x) for x in hubby ]
[31597728, 40240552]
>>> [ id(x) for x in wifey ]
[31597728, 40240552]

此时我们修改 hubby及wifey的元素值,即 姓名和银行存款

首先只修改姓名

>>> hubby[0]='joe'
>>> wifey[0]='lucy'
>>> hubby,wifey
(['joe', ['saving', 100]], ['lucy', ['saving', 100]])
>>> [ id(x) for x in [person,hubby,wifey] ]
[40260872, 40261032, 40260672]
>>> [ id(x) for x in person ]
[31597728, 40240552]
>>> [ id(x) for x in hubby ]
[40281560, 40240552]
>>> [ id(x) for x in wifey ]
[40284800, 40240552]

然后修改hubby的存款,会发现hubby和wifey的存款同时被修改了,这就是因为是浅拷贝的原因。

>>> hubby[1][1] = 50.00
>>> hubby,wifey
(['joe', ['saving', 50.0]], ['lucy', ['saving', 50.0]])
>>> [ id(x) for x in [person,hubby,wifey] ]
[40260872, 40261032, 40260672]
>>> [ id(x) for x in person ]
[31597728, 40240552]
>>> [ id(x) for x in hubby ]
[40281560, 40240552]
>>> [ id(x) for x in wifey ]
[40284800, 40240552]

而我们此时查看saving 的值,我们会发现saving的值也被修改了。

>>> saving
['saving', 50.0]

 

序列类型对象的浅拷贝是默认类型的拷贝。常用情况如下 

  • 完全切片操作
  • 工厂函数 list() dict()
  • copy 模块的copy函数

为什么name元素在wifey进行重新赋值的时候,hubby没有被修改呢? 因为字符串是不可变类型,第二个saving是列表类型为可变类型。所以在进行拷贝的时候 对字符串进行显示拷贝,创建新的字符串对象并进行赋值。而列表对象则进行浅拷贝了。所以无论我们怎么修改 列表对象的引用都不会变,而修改的都是列表引用对象的值。

#第一次修改saving为50 
>>> hubby[1][1] = 50.00
>>> hubby,wifey
(['joe', ['saving', 50.0]], ['lucy', ['saving', 50.0]])
>>> [ id(x) for x in [person,hubby,wifey] ]
[40260872, 40261032, 40260672]
>>> [ id(x) for x in person ]
[31597728, 40240552]
>>> [ id(x) for x in hubby ]
[40281560, 40240552]
>>> [ id(x) for x in wifey ]
[40284800, 40240552]

#第二次修改saving为60 
>>> hubby[1][1] = 60.00
>>> hubby,wifey
(['joe', ['saving', 60.0]], ['lucy', ['saving', 60.0]])
>>> [ id(x) for x in [person,hubby,wifey] ]
[40260872, 40261032, 40260672]
>>> [ id(x) for x in person ]
[31597728, 40240552]
>>> [ id(x) for x in hubby ]
[40281560, 40240552]
>>> [ id(x) for x in wifey ]
[40284800, 40240552]

 

深拷贝的实现 通过copy模块

>>> saving = ['saving',100]
>>> id(saving)
42599848
>>> person = ['name',saving]
>>> hubby = person[:]
#使用深拷贝来创建wifey
>>> import copy
>>> wifey = copy.deepcopy(person)
>>> hubby,wifey
(['name', ['saving', 100]], ['name', ['saving', 100]])
>>> [ id(x) for x in [person,hubby,wifey] ]
[42620168, 42621528, 42635712]
>>> [ id(x) for x in person ]
[3810464, 42599848]
>>> [ id(x) for x in hubby ]
[3810464, 42599848]
>>> [ id(x) for x in wifey ]
[3810464, 42638272]
#修改hubby和wifey的姓名
>>> hubby[0]='joe'
>>> wifey[0]='lucy'
>>> hubby,wifey
(['joe', ['saving', 100]], ['lucy', ['saving', 100]])
>>> [ id(x) for x in [person,hubby,wifey] ]
[42620168, 42621528, 42635712]
>>> [ id(x) for x in person ]
[3810464, 42599848]
>>> [ id(x) for x in hubby ]
[42641360, 42599848]
>>> [ id(x) for x in wifey ]
[42643936, 42638272]
>>>#修改hubby 的存款,发现wifey没有变化
>>> hubby[1][1] =50.00
>>> hubby,wifey
(['joe', ['saving', 50.0]], ['lucy', ['saving', 100]])
>>> [ id(x) for x in [person,hubby,wifey] ]
[42620168, 42621528, 42635712]
>>> [ id(x) for x in person ]
[3810464, 42599848]
>>> [ id(x) for x in hubby ]
[42641360, 42599848]
>>> [ id(x) for x in wifey ]
[42643936, 42638272]

 

关于浅拷贝的操作建议:

非容器类型 (数字字符串布尔值 或其他原子类型对象,eg代码,类型,xrange等)没有浅拷贝概念

如果元组变量只包含原子类型对象,对他的深拷贝将不会进行。

>>> #saving 是元组并且只包含原子类型对象
... saving = ('saving',100)
>>> id(saving)
42622528
>>> person = ['name',saving]
>>> hubby = person[:]
>>> import copy
>>> wifey = copy.deepcopy(person)
>>> hubby,wifey
(['name', ('saving', 100)], ['name', ('saving', 100)])
>>> [ id(x) for x in [person,hubby,wifey] ]
[42685744, 42620168, 42621528]
>>> [ id(x) for x in person ]
[3810464, 42622528]
>>> [ id(x) for x in hubby ]
[3810464, 42622528]
>>> [ id(x) for x in wifey ] #可以看到wifeydeepcopy了并不是深拷贝
[3810464, 42622528]

 

####end

 

posted @ 2018-07-17 17:38  panzq  阅读(146)  评论(0编辑  收藏  举报