简单来说,copy 复制创建新的容器,而引用容器内元素的地址不变。而 deepcopy 也对容器内的容器元素进行复制。
但是这种复制具体是什么体现呢?是否只是对第一层容器元素进行了复制?写了一段代码验证。
from collections.abc import Iterable
from pprint import pprint
from copy import deepcopy
def get_id(obj):
if isinstance(obj, Iterable):
return tuple((id(i), get_id(i)) for i in obj)
else:
return None
ls = [1, 1, [2, 22], [3, [3, 33]]]
ids = lambda obj: pprint((id(obj), get_id(obj)))
ids(ls)
ids(ls.copy())
ids(deepcopy(ls))
(139690047990528,
((139690060546288, None),
(139690060546288, None),
(139690050031936, ((139690060546320, None), (139690060546960, None))),
(139690048039680,
((139690060546352, None),
(139690048043392, ((139690060546352, None), (139690060547312, None)))))))
(139690048041088,
((139690060546288, None),
(139690060546288, None),
(139690050031936, ((139690060546320, None), (139690060546960, None))),
(139690048039680,
((139690060546352, None),
(139690048043392, ((139690060546352, None), (139690060547312, None)))))))
(139690048041088,
((139690060546288, None),
(139690060546288, None),
(139690048039808, ((139690060546320, None), (139690060546960, None))),
(139690047983488,
((139690060546352, None),
(139690050043008, ((139690060546352, None), (139690060547312, None)))))))
结论:
- 数字类型元素的引用地址始终不变,同一个数字可被多次引用。
- copy 只改变了最外层列表的地址,内部元素均相同。
- deepcopy 改变了最外层以及内部所有列表(包括列表元素的列表元素)的地址。
ls.copy()
和deepcopy(ls)
的地址相同,猜测原因是程序中ls.copy
返回的数据在打印结束后没有被使用了,便被销毁,同一个地址又用来存储deepcopy(ls)
返回的结果。