【学习笔记】Python深浅拷贝copy解析
一、列表的赋值(一般用于读操作)
这个和列表的深浅拷贝其实没有关系,就是一个赋值操作;
list1和list2指向的是同一片内存地址;
即,你家有套房子,叫清华楼A栋101室,也叫清华楼A栋1层1室,名字不同,但是同一个房子。
1 list1 = [ 2 "Jason", 3 18, 4 [1, 2] 5 ] 6 list2 = list1 # list1和list2指向的是同一个,改1个,另一个也会变 7 print(list1) # ['Jason', 18, [1, 2]] 8 print(list2) # ['Jason', 18, [1, 2]] 9 print(id(list1)) # 2133190750464 10 print(id(list2)) # 2133190750464
二、列表的浅拷贝copy(一般用于写操作)
如果只是读操作,没必要进行拷贝,浪费内存地址;
浅拷贝copy,会在一片新的内存地址,创建一个新的列表,但是列表内的元素,不管该元素是可变类型,还是不可变类型,新列表的元素还是指向旧列表元素的内存地址;
这样在进行写操作,即增删改时:
如果列表的元素都是不可变类型,那么没什么问题,修改一个列表,是不影响另外一个列表的;
如果列表的元素中有可变类型,那么,修改一个列表的可变类型中的元素时,另一个列表中的可变类型的元素也会被修改。
浅拷贝copy就是,你家有套房子(list1),你又新买了套房子(list2),但还是你住,所以,房子里的人没有变化,列表里的元素也没有变化。
1 list1 = [ 2 "Jason", 3 18, 4 [1, 2] 5 ] 6 list3 = list1.copy() 7 print(id(list1)) # 2775467405632 8 print(id(list3)) # 2775467374784 9 print(id(list1[0])) # 2775467372784 10 print(id(list3[0])) # 2775467372784 11 print(id(list1[2])) # 2775466065152 12 print(id(list3[2])) # 2775466065152 13 list1[1] = 20 14 list1[2][0] = 333 15 print(list1) # ['Jason', 20, [333, 2]] 16 print(list3) # ['Jason', 18, [333, 2]]
可以看到,在浅拷贝copy模式下,list3和list1的内存地址发生了改变,即,list3不是指向list1指向的内存地址,而是在新的内存地址创建了一个新的列表;
但是,list3中的元素,不管是可变类型,还是不可变类型,都指向了list1中元素指向的内存地址,新瓶装旧酒;
对于不可变类型元素,一个列表元素修改后,并不改变该元素的值,而是会在新的内存地址创建新的值,并和该列表的元素建立新的映射关系,并不会影响另一个列表元素和旧值的映射关系;
list1[1]的修改并没有影响到list3[1];
对于可变类型元素,一个列表元素修改后,会在该元素对应的旧内存地址中直接修改值,新、旧列表元素都没有建立新的映射关系,会影响另一个列表元素。
所以,同时对不可变类型list1[1]和可变类型list1[2]中的元素list1[2][0]修改后,list3[1]不受影响,但list3[2]中的元素list2[2][0]被修改了。
三、列表的深拷贝copy(一般用于写操作)
深拷贝copy,会在一片新的内存地址,创建一个新的列表,
新列表内的元素,如果是不可变类型,新列表的元素还是指向旧列表元素的内存地址,如果是可变类型,则在新内存地址中创建新的元素拷贝;
如果是可变类型嵌套,比如列表里的元素还是列表,同理;
这样在进行写操作,即增删改时,修改一个列表的元素,是不会影响到另一个列表的元素的;
针对可变类型的元素,深拷贝copy就是,你家有套房子(list1),你又新买了套房子(list4),你自己住房子list1,你双胞胎弟弟住房子list4。
1 import copy 2 3 list1 = [ 4 "Jason", 5 18, 6 [1, 2] 7 ] 8 list4 = copy.deepcopy(list1) 9 print(id(list1)) # 1904758082112 10 print(id(list4)) # 1904758079744 11 print(id(list1[1])) # 1904752421712 12 print(id(list4[1])) # 1904752421712 13 print(id(list1[2])) # 1904757785472 14 print(id(list4[2])) # 1904758158336 15 list1[1] = 20 16 list1[2][0] = 333 17 print(list1) # ['Jason', 20, [333, 2]] 18 print(list4) # ['Jason', 18, [1, 2]]
可以看到,深拷贝copy中,对于可变类型元素list1[2],list4[2]在新的内存地址中建立了新的元素拷贝;
这样,在修改list1中的元素时,list2中的元素不受影响。
PS:参考资料:老男孩培训Egon老师视频 (https://www.bilibili.com/video/BV1QE41147hU) P96-P98
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示