首先,这三种形式是有关联的,这三种形式应该与对象和身份判断共同理解,分析对象的id和赋值的引用是关键。
最根本的原则:深浅拷贝的区别是用在组合对象中,像是列表、字典、元祖、数字、字符的几种组合,这样深浅拷贝有区别。
赋值,拷贝对象的引用,id相同。
a=5
b=a
print(id(a),id(b))
输入结果的id 一定是相同的。
2744560517488 2744560517488
针对深浅拷贝,需要从组合类型中分析,浅拷贝是复制数据,但是不复制引用,总结来说就是只是把数据给了一个新的空间,但是与原来的数据还有着千丝万缕的关系,不是一个完整的独立个体。
ls1=[1,[2,3]] #创建列表对象并赋给变量ls1
ls2=ls1[:] #从前到后所有进行读取 #通过ls1[:]将ls1的所有元素切片生成新对象并赋给ls2
print('ls1和ls2的值分别为:',ls1,ls2)
print('ls1和ls2的内存地址分别为:',id(ls1),id(ls2))
ls1和ls2的值分别为: [1, [2, 3]] [1, [2, 3]]
ls1和ls2的内存地址分别为: 1718324918528 1718328057920
如上的结果,值完全复制了,给了一个新的内存地址,这是浅拷贝,当然深拷贝也是一个新的内存地址,最大的区别是赋值和里面元素的id.
print('ls1[1]和ls2[1]的内存地址分别为:',id(ls1[1]),id(ls2[1]))
ls1[1][0]=5 #将ls1下标为1的列表元素(即ls[1])中下标为0的元#素值修改为5
print('ls1和ls2的值分别为:',ls1,ls2)
从这个结果就可以看出,id相同,值相同,因为 这两个数据之间的引用关系仍旧存在,所以导致这样的结果。
ls1[1]和ls2[1]的内存地址分别为: 1718324631296 1718324631296
ls1和ls2的值分别为: [1, [5, 3]] [1, [5, 3]]
对于深拷贝来说,会形成两个完全独立的个体。
import copy #导入copy模块
ls1=[1,[2,3]] #创建列表对象并赋给变量ls1
ls2=copy.deepcopy(ls1) #通过调用deepcopy函数复制ls1生成新对象并赋给ls2
print('ls1和ls2的值分别为:',ls1,ls2)
print('ls1和ls2的内存地址分别为:',id(ls1),id(ls2))
print()
print('ls1[1]和ls2[1]的内存地址分别为:',id(ls1[1]),id(ls2[1]))
ls1[1][0]=5 #将ls1下标为1的列表元素(即ls[1])中下标为0的元素值修改为5
print('ls1和ls2的值分别为:',ls1,ls2)
ls1和ls2的值分别为: [1, [2, 3]] [1, [2, 3]]
ls1和ls2的内存地址分别为: 1940159427904 1940159497728
ls1[1]和ls2[1]的内存地址分别为: 1940156221312 1940159425408
ls1和ls2的值分别为: [1, [5, 3]] [1, [2, 3]]
运行上述代码,可以看出,赋值后两个对象的id肯定是不同的,这点与浅拷贝一致,但是内部元素的索引已经被彻底破坏,因此,内部元素的id一定是不同的,具体其内存地址。
同样,对其中一个组合进行值的修改,另一个就不会任何变化。
这就是深浅拷贝的区别,最关键的是针对组合对象而言,才有这种性质。