python中深复制与浅复制

先看一下官方文档给的区别及注意(python3.6):

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):
A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.
Two problems often exist with deep copy operations that don’t exist with shallow copy operations:
Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop.
Because deep copy copies everything it may copy too much, such as data which is intended to be shared between copies.
The deepcopy() function avoids these problems by:
keeping a “memo” dictionary of objects already copied during the current copying pass; and
letting user-defined classes override the copying operation or the set of components copied.

翻译:

浅复制和深复制之间的区别仅与复合对象(包含其他对象的对象,如列表或类实例)相关:
浅拷贝构造一个新的复合对象,然后(尽可能)将引用插入到原始对象中。
深层副本构造一个新的复合对象,然后递归地将原始对象中找到的对象的副本插入到新的复合对象。
对于浅复制操作不存在的但是深拷贝操作常常存在两个问题:
递归对象(复合对象,直接或间接包含对自身的引用的)可能会导致递归循环。
因为深拷贝复制了可能拷贝太多的所有内容,例如打算在拷贝之间共享的数据。
deepcopy()函数通过以下方法避免了这些问题:
保留在当前复制过程中已经复制的对象的“备忘录”字典和让用户定义的类覆盖复制操作或复制的组件集合。

我总结了几点用法:

  • 如果改变的是可变对象里的不可变对象,复制对象与原对象互不影响(深复制和浅复制都适用)
  • 如果改变的是可变对象里的可变对象:浅复制中,原对象和复制对象相互影响;深复制里不相互影响

import copy

list_1=[1,2,3]
list_2=copy.copy(list_1)
print("case 1:")
print("list_1",id(list_1[0]),id(list_1[1]),id(list_1[2]),sep=',')
print("list_2",id(list_2[0]),id(list_2[1]),id(list_2[2]),sep=',',end="\n\n")
list_1[0]='a'
print("list_1",id(list_1[0]),id(list_1[1]),id(list_1[2]),sep=',')
print("list_2",id(list_2[0]),id(list_2[1]),id(list_2[2]),sep=',',end="\n\n")
#改变list_1中的第一个对象,list_2的第一个并没有改变,由此可以看出
#在浅复制中,改变的元素是不可变对象(int,float,str等)不会影响浅复制对象

list_1=[1,2,[3,4]]
list_2=copy.copy(list_1)
print("case 2:")
print(id(list_1[0]),id(list_1[2]),id(list_1[2][0]),sep=',')
print(id(list_2[0]),id(list_2[2]),id(list_2[2][0]),sep=',',end='\n\n')
list_1[2][0]='a'
print(id(list_1[0]),id(list_1[2]),id(list_1[2][0]),sep=',')
print(id(list_2[0]),id(list_2[2]),id(list_2[2][0]),sep=',',end='\n\n')
#浅复制里改变可变子对象的值,都发生变化

list_1=[1,2,[3,4]]
list_2=copy.deepcopy(list_1)
print("case 3:")
print(id(list_1[0]),id(list_1[2]),id(list_1[2][0]),sep=',')
print(id(list_2[0]),id(list_2[2]),id(list_2[2][0]),sep=',',end='\n\n')
list_1[0]='a'
print(id(list_1[0]),id(list_1[2]),id(list_1[2][0]),sep=',')
print(id(list_2[0]),id(list_2[2]),id(list_2[2][0]),sep=',')
#可以看出子对象[3,4]的id都已经不同了,说明他们已经不是一个对象了
#所以改变子对象[3,4]的内容不会相互影响;而改变的元素是不可变对象(int,float,str等)也不会影响深复制对象

结果:

case 1:
list_1,1584589936,1584589968,1584590000
list_2,1584589936,1584589968,1584590000

list_1,1865113927440,1584589968,1584590000
list_2,1584589936,1584589968,1584590000

case 2:
1584589936,1865116545672,1584590000
1584589936,1865116545672,1584590000

1584589936,1865116545672,1865113927440
1584589936,1865116545672,1865113927440

case 3:
1584589936,1865116545800,1584590000
1584589936,1865116545480,1584590000

1865113927440,1865116545800,1584590000
1584589936,1865116545480,1584590000

猜你喜欢

转载自blog.csdn.net/liunan199481/article/details/80081557