深浅拷贝在python中经常使用,其区别的外在表现是:
使用浅拷贝,当原容器对象中可变对象中有元素发生变化,拷贝得到的对象也会变化。而使用深拷贝时,不会有这种问题。
# -*- coding: utf-8 -*-
# @File : 浅拷贝.py
# @Author : Runpeng Zhang
# @Date : 2020/2/10
# @Desc : 演示介绍深拷贝和浅拷贝的区别,该文件演示浅拷贝
# copy浅拷贝,没有拷贝子对象,所以原始数据改变,子对象会改变
import copy
# 定义一个列表,其中第一个元素是可变类型
list1 = [[1, 2], 'fei', 66]
# 进行浅copy
list2 = copy.copy(list1)
# 对象地址是否相同
print(id(list1))
print(id(list2))
"""
对象的地址是不同的
2313807246344
2313789591048
"""
# 第一个元素地址是否相同
print(id(list1[0]))
print(id(list2[0]))
"""
结果是相同的
2313807270216
2313807270216
"""
# 第二个元素地址是否相同
print(id(list1[1]))
print(id(list2[1]))
"""
结果是相同的
2313789572576
2313789572576
"""
# 改变第一个值,查看复制对象变化
list1[0][0] = 2
print(list2)
"""
结果是复制对象也发生了变化[[2, 2], 'fei', 66]
"""
# 改变第二个值,查看复制对象变化
list1[1] = 'ge'
print(list2)
"""
结果是复制对象没发生变化[[2, 2], 'fei', 66]
"""
# -*- coding: utf-8 -*-
# @File : 深拷贝.py
# @Author : Runpeng Zhang
# @Date : 2020/2/10
# @Desc : 演示介绍深拷贝和浅拷贝的区别,该文件演示深拷贝
# 深拷贝,包含对象里面的自对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变
import copy
# 定义一个列表,其中第一个元素是可变类型
list1 = [[1, 2], 'fei', 66]
# 进行深copy
list2 = copy.deepcopy(list1)
# 对象地址是否相同
print(id(list1))
print(id(list2))
"""
对象的地址是不同的
2313807246344
2313789591048
"""
# 改变第一个值,查看复制对象变化
list1[0][0] = 2
print(list2)
"""
结果是复制对象始终没有发生变化[[1, 2], 'fei', 66]
"""
# 改变第二个值,查看复制对象变化
list1[1] = 'ge'
print(list2)
"""
结果是复制对象始终没有发生变化[[2, 2], 'fei', 66]
"""
当我们声明list1 = [[‘a’, ‘b’], 1, 2]时,计算机做了这些事:
1、在内存中开辟一段空间,用来存放字符a,b和数字1,数字2
2、在内存开辟一段空间,用来存放一个列表,我们称为list2。list2中存放两个指针,分别指向字符a和b
3、在内存开辟一段空间,用来存放一个列表lsit1,list1中存放三个指针,分别指向list2,数字1和数字2
当执行浅拷贝lsit3 = copy.copy(list1)时,计算机开辟一段内存给list3,list3保存三个指针,分别指向list2,数字1和数字2。当执行list1[0][0] = 'c’时,list2对象修改了,而list3的第一个指针指向list2,所以我们看到list3的第一个元素也变了。
当执行深拷贝lsit4 = copy.copy(list1)时,计算机开辟一段内存给list4,和浅拷贝不同的是,计算机同时开辟一段空间给新的列表,我们称为lsit5。list5中保存2个指针,分别指向字符a和b。
同时list4保存三个指针,分别指向list5,数字1和数字2。此时,当执行list1[0][0] = 'c’时,list2对象修改了,但list4的第一个指针指向list5,list5并没有修改,所以list4没有改变。
总结:深拷贝会把可变对象也拷贝一份,而浅拷贝不会。
上面例子中说的是列表(可变对象)的拷贝,那对于元组,字符等不可不对象呢?
答案是,对不可不对象,其实不存在深浅拷贝的问题。无论怎么拷贝,效果都是新建立一个指向不可变对象的指针而已。