那为什么要深拷贝呢?
修改列表内的不可变对象元素
上面的栗子是直接添加元素,来看看修改元素会怎么样
# 不可变元素 import copy old_list = [1, 2, "string", (1, 2,)] new_list = copy.copy(old_list) old_list[1] += 22 old_list[2] += "s" old_list[3] += (3,) print("Old list:", old_list) print("New list:", new_list) # 输出结果 Old list: [1, 24, 'strings', (1, 2, 3)] New list: [1, 2, 'string', (1, 2)]
修改 old_list 的三种不可变对象元素,均不会同步给 new_list
修改不可变对象的原理图
修改列表内的可变对象元素
# 可变元素 import copy old_list = [[1, 2], [3, 4]] new_list = copy.copy(old_list) old_list[0][0] += 99 old_list[1][0] += 97 print("Old list:", old_list, "old list id:", id(old_list), " old list[0] id:", id(old_list[0])) print("new list:", new_list, "new list id:", id(new_list), " new list[0] id:", id(new_list[0])) # 输出结果 Old list: [[100, 2], [100, 4]] old list id: 4430308096 old list[0] id: 4430302400 new list: [[100, 2], [100, 4]] new list id: 4430308416 new list[0] id: 4430302400
从输出结果看到
- 两个变量保存了不同的对象引用
- 但是可变对象元素的内存地址仍然是同一个
修改可变对象的原理图
总结
- 修改可变对象是在原始对象上直接操作的
- 浅拷贝产生的新对象存储的仍然是原始对象的内存地址
- 所以修改可变对象的时候,新对象的值也会被同步修改,因为新旧列表对象的元素的引用是指向同一个内存地址
- 当修改可变对象的时候,不满足一开始说的实际应用场景,所以诞生了深拷贝
深拷贝
- 创建一个新对象,且存储的对象引用也是新的
- 深,意味着会把所有子元素对象也复制生成一个新对象
栗子一
# 深拷贝 old_list = [[1, 2], [3, 4]] new_list = copy.deepcopy(old_list) old_list[0][0] += 99 old_list[1][0] += 97 print("Old list:", old_list, "old list id:", id(old_list), " old list[0] id:", id(old_list[0])) print("new list:", new_list, "new list id:", id(new_list), " new list[0] id:", id(new_list[0])) # 输出结果 Old list: [[100, 2], [100, 4]] old list id: 4430308480 old list[0] id: 4430211392 new list: [[1, 2], [3, 4]] new list id: 4430308096 new list[0] id: 4430308864
从输出结果看到
- 两个变量保存了不同的对象引用
- 可变对象元素(子对象)的内存地址也是不同的
栗子二
假设是一个三维列表呢
# 深拷贝-三维数组 old_list = [[1, [10, 9]], [3, 4]] new_list = copy.deepcopy(old_list) old_list[0][1][0] += 90 print("Old list:", old_list) print("New list:", new_list) # 输出结果 Old list: [[1, [100, 9]], [3, 4]] New list: [[1, [10, 9]], [3, 4]]
两个变量依旧是独立的
深拷贝原理图
浅拷贝的多种实现方式
https://www.cnblogs.com/poloyy/p/15086511.html
面试题:浅拷贝、深拷贝的区别
- 浅拷贝和深拷贝只有在可变对象才会生效,不可变对象的赋值操作、浅拷贝、深拷贝的效果是一样的
- 浅拷贝会将对象复制生成一个新对象,但新对象仍然存储原始对象的引用,当原始对象是可变对象,然后修改它的值时,新旧对象会同时改变
- 深拷贝不仅会将对象复制生成一个新对象,且所有原始对象都会复制生成新对象,即使原始对象是可变对象,新对象存储的对象引用也是新的,所以改变旧对象的可变对象时,不会影响新对象