浅拷贝
所谓浅拷贝就是拷贝了对象的索引,而不是重新建立一个对象。
创建一个对象之后,然后将它赋值给另一个变量的时候,Python并没有拷贝这个对象,而是拷贝了这个对象的引用。
常见的浅拷贝:
- 序列对象的链接、重复
- list()、dict()等工厂函数
- copy模块的copy函数
>>> person = ['name',['savings',100.00]]
>>> hubby = person[:] #slice copy
>>> wifey = list(person) #fac fun copy
>>> [id(x) for x in person,hubby,wifey]
[140596031130656, 140596031130584, 140596031185264]
>>> hubby[0] = 'joe'
>>> wifey[0] = 'jane'
>>> hubby,wifey
(['joe', ['savings', 100.0]], ['jane', ['savings', 100.0]])
>>> hubby[1][1] = 50.00
>>> hubby,wifey
(['joe', ['savings', 50.0]], ['jane', ['savings', 50.0]])
首先我们创建了一个person对象,并通过切片和工厂函数的方式拷贝给hubby和wifey。然后分别对hubby和wifey的name做了修改,输出显示没有问题。之后修改hubby的存款为50,wifey的存款没做修改,输出显示wifey的存款也变成了50。
原因:两个列表的第一个元素是字符串,是不可修改的。第二个元素是列表,是可修改的。当进行的是浅拷贝的时候,字符串被显示的拷贝并创建了新的字符串对象,而列表只是复制了其引用。
>>> person = ['name',['savings',100.00]]
>>> hubby = person[:] #slice copy
>>> wifey = list(person) #fac fun copy
>>>
>>> [id(x) for x in person]
[140596032343664, 140596031130872]
>>> [id(x) for x in hubby]
[140596032343664, 140596031130872]
>>> [id(x) for x in wifey]
[140596032343664, 140596031130872]
>>>
>>> hubby[0] = 'joe'
>>> wifey[0] = 'jane'
>>> hubby[1][1] = 50.00
>>>
>>> [id(x) for x in hubby]
[140596031220392, 140596031130872]
>>> [id(x) for x in wifey]
[140596031167632, 140596031130872]
深拷贝
与浅拷贝对立,对于可变的元素拷贝的是对象,而不是对象的索引。
使用深拷贝需要使用copy模块的deepcopy函数copy.deepcope()
>>> import copy
>>> person = ['name',['savings',100.00]]
>>> hubby = copy.deepcopy(person)
>>> wifey = copy.deepcopy(person)
>>>
>>> [id(x) for x in person]
[140596032343664, 140596031185264]
>>> [id(x) for x in hubby]
[140596032343664, 140596031227304]
>>> [id(x) for x in wifey]
[140596032343664, 140596031227160]
以下有两点说明:
1. 非容器类型(比如数字,字符串和其他‘原子’类型的对象,像代码,类型和xrange对象等)没有被拷贝一说,浅拷贝是用完全切片操作来完成的。
2. 如果元组变量只包含原子类型对象,对它的深拷贝不会进行。