浅拷贝和深拷贝

1、对象赋值实际上是简单的对象引用。如下代码,a和b引用了同一块内存区域,这块内存区域存放着数字5。

>>> a = 5
>>> b = a
>>> id(a)
19193872
>>> id(b)
19193872

 

2、浅拷贝

>>> listO = ['string', ['list', 'list']]
>>> list1 = listO[:] #用切片操作默认为浅拷贝
>>> list2 = list(listO) #用工厂方法也是浅拷贝
>>> [id(x) for x in listO, list1, list2] #三个list对象存放在不同内存区域
[29443456, 29445176, 29153480]

>>> [id(x) for x in listO] #但是浅拷贝后,容器的元素是原来对象元素的引用,三个list对象的元素都指向相同的内存区域
[19318432, 29443416]
>>> [id(x) for x in list1]
[19318432, 29443416]
>>> [id(x) for x in list2]
[19318432, 29443416]

>>> list1[0] = 'string1' #字符串是不可变对象,所以创建了新的string对象,并使list1[0]指向它
>>> list1
['string1', ['list', 'list']]
>>> list2  #list2[0]还指向原来的对象
['string', ['list', 'list']]

>>> list1[1].append('add') #列表是可变的对象,在原对象上修改,没有创建新对象
>>> list1
['string1', ['list', 'list', 'add']]
>>> list2 #list1[1]和list2[1]指向同一对象,所以list2[1]也被修改了
['string', ['list', 'list', 'add']]

3、深拷贝,或者说完全拷贝

>>> import copy
>>> listO = ['string', ['list', 'list']]
>>> list1 = listO[:]
>>> list2 = copy.deepcopy(listO)
>>> [id(x) for x in listO, list1, list2]
[29442896, 29443456, 29451688]

>>> [id(x) for x in listO]
[19318432, 29452688]
>>> [id(x) for x in list1]
[19318432, 29452688]
>>> [id(x) for x in list2] #注意这里和浅拷贝的不同,list2[1]和list1[1]指向不同的对象,而不可变类型元素list2[0]还是指向原来的对象
[19318432, 29483056]

4、关于拷贝操作

  • 非容器类型没有拷贝一说
  • 如果容器里只包含不可变类型对象,对它的深拷贝将不会进行。(因为深拷贝只是在可变对象上动手脚)
  • 在copy模块中只有两个可用函数:copy()进行浅拷贝操作、deepcopy()进行深拷贝操作

 

posted @ 2012-10-13 12:13  小童鞋  阅读(145)  评论(0编辑  收藏  举报