python的浅拷贝和深拷贝
首先有以下几个概念:
变量:一个元素,具有指向对象的连接空间,也可以理解为是对象的引用;
对象:有分配的一块内存空间,用来存储其代表的值;
引用:一个从变量到对象的指针;
可变对象:可以改变的对象,可以添加、删除、修改对象内部元素的,比如像 列表、字典等;
不可变对象:在python中对象一旦创建,不可再对其内部元素进行修改的对象,比如像 元组、字符串
赋值、浅拷贝:
对于不可变对象赋值时
1
1
31518400
31518400
2
1
31573408
31518400
2
3
31573408
30416576
当a变更赋值对象时,b不会跟着变更
即初始时,a,b被分配了不同一引用同一地址
当a重新赋值为2时,a的指向发生了变化,但是b的指向还是原来的
当b赋值为3时,b的指向发生了改变,但是a的指向未改变
对于可变对象赋值
[1, 2, [4, 5, 6]]
[1, 2, [4, 5, 6]]
[1, 2, [4, 5, 6]]
23299144
23299144
23299240
[7, 2, [4, 5, 6]]
[7, 2, [4, 5, 6]]
[1, 2, [4, 5, 6]]
23299144
23299144
23299240
[7, 2, [9, 5, 6]]
[7, 2, [9, 5, 6]]
[1, 2, [9, 5, 6]]
23299144
23299144
23299240
[7, 2, [10, 5, 6]]
[7, 2, [10, 5, 6]]
[1, 2, [10, 5, 6]]
23299144
23299144
23299240
可以看到,直接赋值时,a,c会同步变化,而使用浅拷贝的b有时不会随着a、c变化
初始a,b指向同一地址,c指向另外一个地址
当a[0]变化时,a[0]和b[0]的指向改变,c[0]不变
当里面的子列表发生改变的时候,即a[2][0]改变,a[2][0],b[2][0],c[2][0]引用的地址全部改变
当c里面的子列表发生改变时,即c[2][0]改变,a,b,c同时发生改变
所以对于可变对象,赋值的引用不会改变,而浅拷贝只拷贝对象的第一层,即第一层的引用会变,而其子对象的引用不会改变。
深拷贝
对不可变对象深拷贝
1 1 1 1584631964 1584631964 1584631964 2 1 1 1584631980 1584631964 1584631964
可以看到对于不可变对象,赋值、浅拷贝、深拷贝都不会给新对象开辟内存,而只是拷贝对象的引用
对于可变对象的深拷贝
import copy a = [1, 2, [4, 5, 6]] c = copy.deepcopy(a) print(a) print(c) print(id(a)) print(id(c)) a[0] = 7 print(a) print(c) print(id(a)) print(id(c)) a[2][0] = 9 print(a) print(c) print(id(a)) print(id(c)) c[2][0] = 10 print(a) print(c) print(id(a)) print(id(c))
[1, 2, [4, 5, 6]] [1, 2, [4, 5, 6]] 25546632 25546568 [7, 2, [4, 5, 6]] [1, 2, [4, 5, 6]] 25546632 25546568 [7, 2, [9, 5, 6]] [1, 2, [4, 5, 6]] 25546632 25546568 [7, 2, [9, 5, 6]] [1, 2, [10, 5, 6]] 25546632 25546568
初始时a指向一个地址,c指向另一个地址
当a[0]发生变化时,a[0]指向发生改变,c[0]不变
当a的子对象发生改变时,即a[2][0]改变,a[2][0]指向发生改变,c[2][0]不变
当c的子对象发生改变时,即c[2][0]改变,a[2][0]指向不变,c[2][0]改变
可以看到,对于可变对象的深拷贝会拷贝其所有的对象
对于python中的切片操作(c = a[:])其实是属于浅拷贝的范围,可以自行将浅拷贝的代码(c = copy.copy(a))换成切片操作,最后输出的结果是一样的。
总结
对于没有子对象的操作,无论是可变对象还是不可变对象,初始对象改变后,浅拷贝和深拷贝的结果都不受影响;
对于有子对象的操作,初始对象改变后,不可变对象浅拷贝和深拷贝的结果都不受影响,可变对象浅拷贝会随着子对象的改变而发生改变,深拷贝不受影响。
所以在某些时候不想改变原始对象,尤其对象中包含子对象时,需要用到深拷贝。
而不关心原始对象的数据时,可以用浅拷贝,节约内存。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下