deepcopy与copy的本质区别——是否为可变对象创建新的对象(内存空间)
以下图片截取自Python Tutorial
代码片段一
- 可变对象list中包含着可变list和不可变对象tuple, 且tuple中不包含可变对象
1
2
3
4
5import copy
l1 = [3, [66, 55, 44], (7, 8, 9)]
l2 = list(l1) # <==> l2 = copy.copy(l1)
# <==> l2 = l1[:]
l3 = copy.deepcopy(l1)
代码片段二
- 可变对象list中包含着可变list和不可变对象tuple, 且tuple中包含可变对象list
1
2
3
4
5import copy
l1 = [3, [66, 55, 44], (7, 8, [1, 2])]
l2 = list(l1) # <==> l2 = copy.copy(l1)
# <==> l2 = l1[:]
l3 = copy.deepcopy(l1)
代码片段三
- 不可变对象中包含可变对象
- 值得强调的是,copy复制tuple时,不会像list那样直接创建新对象,无论tuple中是否有可变对象*
- 除非包含不可变对象,否则deepcopy复制tuple时也不会创建新对象*
1
2
3
4
5
6
7import copy
t1 = (3, [66, 55, 44], (7, 8, [1, 2]))
t2 = t1
t3 = tuple(t1) # <==> t4 = t1[:]
# t5 = copy.copy(t1)
t6 = copy.deepcopy(t1)
t1[1].append(100)
总结
对于不可变对象
- deepcopy与copy操作一样,都不为创建新对象,而是直接引用
- 在后面如果有修改该不可变对象的操作时再创建新对象,此时两个版本的不可变对象地址变得不同
- 这里是Python的常态,比如
tuple(tuple1)
将返回一个tuple1对象的引用而不是副本,当修改tuple1时才会创建新对象 - 因为无论如何,修改不可变对象的不可变部分都不会修改原始对象,所以为了节约内存,Python解释器完全可以将创建新对象保留到修改内容时
对于可变对象
- deepcopy将创建新对象
- copy只复制对象地址
- 后面修改该可变对象时地址不变,而是直接修改内容
总之
deepcopy的目的就是确保,无论如何修改,原始对象和副本之间都完全独立
所以
只要是可能被修改的对象都要复制!!!
不可变对象在复制时会自动新建
故而deepcopy时不可变对象不用创建新对象