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