PythonTip >> 博文 >> 基础与入门

Python中对象浅拷贝和深拷贝

zihua 2013-10-10 16:10:25 点击: 1219 | 收藏


对象赋值实际上是简单的对象引用,也就是说,当你创建一个对象,然后把它赋值给另一个变量的时候,Python并没有拷贝这个对象,而是拷贝了这个对象的引用。

比如这样,

>>> person = ['name', ['savings', 100.00]]
>>> h = person[:]
>>> w = list(person)
>>> [id(x) for x in person, h, w]
[19099440, 19095640, 19130448]

我们创建了一个person,然后使用切片和工厂函数把它赋值给h,w。然后试着修改一下元素的值看一下结果,

>>> h[0] = "aaa"
>>> w[0] = "bbb"
>>> h, w
(['aaa', ['savings', 100.0]], ['bbb', ['savings', 100.0]])
>>> h[1][1] = 200
>>> h, w
(['aaa', ['savings', 200]], ['bbb', ['savings', 200]])
我们发现,修改name的时候w的name没有覆盖h中的name,修改第列表中的第二个元素列表时,他们的值都发生改变了。这种情况就是说仅仅是做了一个浅拷贝。等于说这个新创建的对象是新的,但是它的内容不是,序列类型的对象默认就是浅拷贝。

列表中的第一个元素是不可变的(字符串),第2个元素是可变的(列表),因为如此,当进行浅拷贝时,字符串被拷贝并创建了一个新的对象,而列表元素只是把它的引用复制了一下,并不是它的成员。第2个元素我们修改它的值,它发生了改变,所以w的值也就跟着改变。

那如何进行深拷贝呢,其实也很简单使用copy模块

>>> import copy
>>> w = copy.deepcopy(person)
>>> w
['name', ['savings', 200]]
>>> h = person
>>> h
['name', ['savings', 200]]
>>> h[1][1] = 50
>>> h
['name', ['savings', 50]]
>>> w
['name', ['savings', 200]]
其实copy模块中共有三个方法,我们一般使用copy()和deepcopy()这两个方法,浅拷贝和深拷贝。

需要注意的几点,非容器类型(数字,字符串和其他原子类型的对象,如代码,类型和xrange)没有拷贝一说,如果元素中只包含原子类型对象,对它的深拷贝不会进行,如果是元组类型,也是不会进行深拷贝的,得到的还是一个浅拷贝。

原文链接:http://pythoner.org/wiki/54/

作者:zihua | 分类: 基础与入门 | 标签: 基础与入门 | 阅读: 1219 | 发布于: 2013-10-10 16时 |