Python copy()、deepcopy()与赋值的区别

这个话题以前在写ios那会就总结过,来了python这些也依然存在。也上一段网上总结好的结论。个人觉得写的非常不错。

—–深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响。 

—–而等于赋值,并不会产生一个独立的对象单独存在,他只是将原有的数据块打上一个新标签(增加一个引用),所以当其中一个标签被改变的时候,数据块就会发生变化,另一个标签也会随之改变。

—–而浅复制要分两种情况进行讨论:

1)当浅复制的值是不可变对象(数值,字符串,元组)时和“等于赋值”的情况一样,对象的id值与浅复制原来的值相同

2)当浅复制的值是可变对象(列表和字典)时会产生一个“不是那么独立的对象”存在。有两种情况:

第一种情况:复制的 对象中无 复杂 子对象,原来值的改变并不会影响浅复制的值,同时浅复制的值改变也并不会影响原来的值。原来值的id值与浅复制原来的值不同。

第二种情况:复制的对象中有 复杂 子对象 (例如列表中的一个子元素是一个列表,如果不改变其中复杂子对象,浅复制的值改变并不会影响原来的值。 但是改变原来的值 中的复杂子对象的值  会影响浅复制的值。(复制对象的子对象和原来对象子对象id相同

对于简单的 object,例如不可变对象(数值,字符串,元组),用 shallow copy 和 deep copy 没区别

复杂的 object, 如 list 中套着 list 的情况,shallow copy 中的 子list,并未从原 object 真的「独立」出来。也就是说,如果你改变原 object 的子 list 中的一个元素,你的 copy 就会跟着一起变。这跟我们直觉上对「复制」的理解不同。

下面上一个我写的例子。注意查看其中的内存地址(即id函数打出的值

import copy
tempList = [0,1,2,[3,4]]
testList = tempList
testCopyList = copy.copy(tempList)
testDeepCopyList = copy.deepcopy(testList)
print('tempList address %s' % id(tempList))
print('tempList %s' % tempList)
print('tempList[3]=={0} and address={1}'.format(tempList[3],id(tempList[3])))
print('testList address %s' % id(testList))
print('testList %s' % testList)
print('testList[3]=={0} and address={1}'.format(testList[3],id(testList[3])))
print('testCopyList address %s' % id(testCopyList))
print('testCopyList address %s' % testCopyList)
print('testCopyList[3]=={0} and address={1}'.format(testCopyList[3],id(testCopyList[3])))
print('testDeepCopyList address %s' % id(testDeepCopyList))
print('testDeepCopyList  %s' % testDeepCopyList)
print('testDeepCopyList[3]=={0} and address={1}'.format(testDeepCopyList[3],id(testDeepCopyList[3])))
tempList.append('sign')
print(tempList,testCopyList,testDeepCopyList)
testList[3].append('sign')
print(tempList,testCopyList,testDeepCopyList)

输出结果为:

tempList address 35630336
tempList [0, 1, 2, [3, 4]]
tempList[3]==[3, 4] and address=35629176
testList address 35630336
testList [0, 1, 2, [3, 4]]
testList[3]==[3, 4] and address=35629176
testCopyList address 35651792
testCopyList address [0, 1, 2, [3, 4]]
testCopyList[3]==[3, 4] and address=35629176
testDeepCopyList address 35652552
testDeepCopyList  [0, 1, 2, [3, 4]]
testDeepCopyList[3]==[3, 4] and address=35651912
[0, 1, 2, [3, 4], 'sign'] [0, 1, 2, [3, 4]] [0, 1, 2, [3, 4]]
[0, 1, 2, [3, 4, 'sign'], 'sign'] [0, 1, 2, [3, 4, 'sign']] [0, 1, 2, [3, 4]]

分析:

tempList和testList 是赋值操作,内存地址是同一个。是增加了引用

通过copy操作后的testCopyList虽然有了新的内存地址,但是其中子列表的地址还和testList一样

但是deepcopy操作后的testDeepCopyList和原来testList的子列表相比不同。

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部