Python对象的赋值、浅拷贝和深拷贝机制

Python是一种在运行时确定变量类型和进行内存管理的动态语言,在对象管理上有着和其他语言不太一样的地方。

当你想拷贝一个对象的时候,你不能简单的进制赋值操作,与Java类似,对象间的赋值操作,只是使用了一个指向原对象的引用,而不是真正的实现拷贝。赋值操作可以这样理解,产生一个列表对象,并把这个列表对象的引用赋值给a,然后创建一个指向同一个对象的引用别名b。这从Python内存管理机制中引用计数来说,上述的操作引用计数为2.当一个变量引用计数为0的时候,该对象将会被作为垃圾回收。

a = [1,2,3,4,5]
b = a
print id(a), id(b)
4452585344 4452585344

当需要保留原对象的基础上,新增一个对象的情况下,要使用真正的对象拷贝机制,一般分为两种:浅拷贝和深拷贝。

Python对象的浅拷贝
虽然生成了一个新对象,但是对象内部的属性和内容仍然引用原对象。实现的方法有多种:

import copy
a = [1,2,3,4,5]
b = copy.copy(a) # 使用copy方法
# b = list(a) 在预知对象类型的情况下,使用内建函数list(), dict(), set()
# b = a[:] 
print id(a), id(b)
4379412168 4379413896

虽然产生的是一个新的对象,但是当对象内部有列表等数据的时候,其实还是引用原对象中的内容。

import copy
a = [[1,2],2,3,4,5]
b = copy.copy(a)
a[0].append('hello')
a[1] = 'a'
print id(a), id(b)
4382731584 4382731800
print a, b
[[1, 2, 'hello'], 'a', 3, 4, 5] [[1, 2, 'hello'], 2, 3, 4, 5]

Python对象的深拷贝
当需要完完全全产生一个全新对象的时候,例如拷贝一些容器对象,还必须递归的拷贝其内部引用的对象,可以使用Python的深拷贝。但是使用深拷贝操作,会消耗一定的时间和内存。

import copy
a = [[1,2],2,3,4,5]
b = copy.deepcopy(a)
a[0].append('hello')
a[1] = 'a'
print id(a), id(b)
4375361224 4375362736
print a, b
[[1, 2, 'hello'], 'a', 3, 4, 5] [[1, 2], 2, 3, 4, 5]

另外值得注意的一点是,对于不可变对象比如字符串、数字、元组的操作,没有必要进行拷贝,即使拷贝,仍然会得到一个原对象。

标签: python对象, 浅拷贝, 深拷贝

添加新评论