【学习笔记】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

posted @   ms_linux  阅读(242)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示