一、浅拷贝
-
概念
-
浅拷贝,指的是重新分配一块内存,创建一个新的对象,但里面的元素尽可能是原对象中各个子对象的引用
list1 = [[1,2,3],(4,5,6)]
list2=list(list1)
print("list1 is list2 ?",list1 is list2,id(list1),id(list2))
print(list1)
print(list2)
print("往list1的第一个列表元素中添加999")
list1[0].append(999)
print(list1)
print(list2)
print("给list1的第二个元组元素拼接")
list1[1]+=(1,1)
print(list1)
print(list2)
print("给list1追加一个元素")
list1.append(11111)
print(list1)
print(list2)
"""
list1 is list2 ? False 4411717312 4411981056 -> 可以看到不是同一个元素
[[1, 2, 3], (4, 5, 6)]
[[1, 2, 3], (4, 5, 6)]
往list1的第一个列表元素中添加999 -> 可以看到list2与list1的第一个元素,共同指向一个列表
[[1, 2, 3, 999], (4, 5, 6)]
[[1, 2, 3, 999], (4, 5, 6)]
给list1的第二个元组元素拼接 -> 元组不可变,对list1第二个元组拼接,生成了新的元组,list2 没有引用新元组,因此不受影响
[[1, 2, 3, 999], (4, 5, 6, 1, 1)]
[[1, 2, 3, 999], (4, 5, 6)]
给list1追加一个元素 -> list1和list2 作为整体是两个不同的对象(id不同),因此不共享内存,操作过后list2不会改变
[[1, 2, 3, 999], (4, 5, 6, 1, 1), 11111]
[[1, 2, 3, 999], (4, 5, 6)]
"""
二、深拷贝
-
概念
-
重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联 -
python之中使用copy.deepcopy()来完成深拷贝
import copy
list1 = [[1,2,3],(4,5,6)]
list2=copy.deepcopy(list1)
print("list1 is list2 ?",list1 is list2,id(list1),id(list2))
print(list1)
print(list2)
print("往list1的第一个列表元素中添加999")
list1[0].append(999)
print(list1)
print(list2)
print("给list1的第二个元组元素拼接")
list1[1]+=(1,1)
print(list1)
print(list2)
print("给list1追加一个元素")
list1.append(11111)
print(list1)
print(list2)
"""
可以看到:不论list1 怎么操作都对list2 没有影响
list1 is list2 ? False 4351803072 4352036736 -> 不是用一个元素
[[1, 2, 3], (4, 5, 6)]
[[1, 2, 3], (4, 5, 6)]
往list1的第一个列表元素中添加999
[[1, 2, 3, 999], (4, 5, 6)]
[[1, 2, 3], (4, 5, 6)]
给list1的第二个元组元素拼接
[[1, 2, 3, 999], (4, 5, 6, 1, 1)]
[[1, 2, 3], (4, 5, 6)]
给list1追加一个元素
[[1, 2, 3, 999], (4, 5, 6, 1, 1), 11111]
[[1, 2, 3], (4, 5, 6)]
"""
三、深拷贝带来的问题
-
如果被拷贝的对象是指向自身的引用,那么程序很同一陷入无限的循环
import copy
list1 = [1]
list1.append(list1)
print(list1)
list2 = copy.deepcopy(list1)
print(list2)
"""
[1, [...]]
[1, [...]]
"""
-
上面list1列表中有指向自身的引用,因此list1是一个无限嵌套的列表,但是深度拷贝到list2之后程序没有栈溢出,这是因为深度拷贝函数 deepcopy 中会维护一个字典,记录已经拷贝的对象与其 ID。拷贝过程中,如果字典里已经存储了将要拷贝的对象,则会从字典直接返回,而不是继续调用深拷贝函数 -
deepcopy部分源码 def deepcopy(x, memo=None, _nil=[]):
"""Deep copy operation on arbitrary Python objects.
See the module's __doc__ string for more info.
"""
if memo is None:
memo = {}
d = id(x)
y = memo.get(d, _nil)
if y is not _nil:
return y
...
|