引用,浅拷贝,深拷贝

张开发
2026/5/6 6:43:06 15 分钟阅读
引用,浅拷贝,深拷贝
引用无论是可变数据类型还是不可变的指内部元素如下图第一个示例中的a内部的整型是不可变的内部嵌套的列表是可变的内存地址也会直接引用过来。# 不可变数据类型a[1,2,3,4,5,6]print(a的内存地址为,id(a))baprint(b的内存地址为,id(a))b[0]5print(修改b[0]的值后a的值为:,a)print(修改b的值后a的内存地址为,id(a))print(修改b[0]的值后b的值为:,b)print(修改b的值后b的内存地址为,id(a))a的内存地址为2661007521408b的内存地址为2661007521408修改b[0]的值后a的值为:[5,2,3,4,5,6]修改b的值后a的内存地址为2661007521408修改b[0]的值后b的值为:[5,2,3,4,5,6]修改b的值后b的内存地址为2661007521408#可变数据类型a[1,2,3,[1,2,3],4,5,6]print(a的内存地址为,id(a))baprint(b的内存地址为,id(a))b[3][1,1,3]print(修改b[0]的值后a的值为:,a)print(修改b的值后a的内存地址为,id(b))print(修改b[0]的值后b的值为:,b)print(修改b的值后b的内存地址为,id(b))a的内存地址为2255144316352b的内存地址为2255144316352修改b[3]的值后a的值为:[1,2,3,[1,1,3],4,5,6]修改b[3]的值后a的内存地址为2255144316352修改b[3]的值后b的值为:[1,2,3,[1,1,3],4,5,6]修改b[3]的值后b的内存地址为2255144316352浅拷贝浅拷贝只会拷贝最外层的内存地址将拷贝后的值重新分配内存空间内部的可变数据类型的数据还是引用的原来的。因此对于不可变数据数据类型如果浅拷贝后更改数据原数据不会发生变化对于可变数据类型更改内部的数据后原数据也会跟着发生变化# 修改不可变数据类型的值a[1,2,3,[1,2,3],4,5,6]print(a的内存地址为,id(a))bcopy.copy(a)print(b的内存地址为,id(b))b[0]5print(修改b[0]的值后a的值为:,a)print(修改b的值后a的内存地址为,id(a))print(修改b[0]的值后b的值为:,b)print(修改b的值后b的内存地址为,id(b))a的内存地址为1967541742656b的内存地址为1967541742912#浅拷贝将拷贝后的值重新分配内存空间修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]# 修改的是整型所以a的值不变修改b的值后a的内存地址为1967541742656修改b[0]的值后b的值为:[5,2,3,[1,2,3],4,5,6]# 变的只有b的值修改b的值后b的内存地址为1967541742912#修改整个可变数据类型的值原对象不受影响a[1,2,3,[1,2,3],4,5,6]print(a的内存地址为,id(a))bcopy.copy(a)print(b的内存地址为,id(b))b[3][1,1,5]# 将b[3]的整个值给替换了print(修改b[0]的值后a的值为:,a)print(修改b的值后a的内存地址为,id(a))print(修改b[0]的值后b的值为:,b)print(修改b的值后b的内存地址为,id(b))a的内存地址为2258999209408b的内存地址为2258999209600修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为2258999209408修改b[0]的值后b的值为:[1,2,3,[1,1,5],4,5,6]修改b的值后b的内存地址为2258999209600# 只修改嵌套列表中的其中一个元素的值原列表会跟着变化a[1,2,3,[1,2,3],4,5,6]print(a的内存地址为,id(a))bcopy.copy(a)print(b的内存地址为,id(b))b[3][0]0print(修改b[0]的值后a的值为:,a)print(修改b的值后a的内存地址为,id(a))print(修改b[0]的值后b的值为:,b)print(修改b的值后b的内存地址为,id(b))a的内存地址为2184038935616b的内存地址为2184038935872修改b[0]的值后a的值为:[1,2,3,[0,2,3],4,5,6]修改b的值后a的内存地址为2184038935616修改b[0]的值后b的值为:[1,2,3,[0,2,3],4,5,6]修改b的值后b的内存地址为2184038935872上述在将b[3] 完全替换和只修改其中一个值引起的a的变化原因是在bcopy.copy(a)后虽然b将[1,2,3,[1,2,3],4,5,6]整个列表重新放在了另一个存储空间中但是浅拷贝只复制对象本身也就是只复制最外面的一层a和b里面的[1,2,3]指向的还是同一个内存地址。在将b[3]完全替换为[1,1,3]后这是另一个列表和[1,2,3]指向的不再是同一个内存地址所以a不会变化。但是如果只修改b[3][0]0,是直接对[1,2,3]这个内存地址进行的修改所以a会跟着变化深拷贝深拷贝和浅拷贝一样也会将拷贝后的数据放到另一个存储空间中不同的是深拷贝递归复制所有子对象完全独立。也就是说无论如何修改b的值a的值都不会变。# 修改不可变数据只改变b不会改变aa[1,2,3,[1,2,3],4,5,6]print(a的内存地址为,id(a))bcopy.deepcopy(a)print(b的内存地址为,id(b))b[0]0print(修改b[0]的值后a的值为:,a)print(修改b的值后a的内存地址为,id(a))print(修改b[0]的值后b的值为:,b)print(修改b的值后b的内存地址为,id(b))a的内存地址为2298910436544b的内存地址为2298910436736修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为2298910436544修改b[0]的值后b的值为:[0,2,3,[1,2,3],4,5,6]修改b的值后b的内存地址为2298910436736#将内部嵌套列表完全修改只改变b不会改变aa[1,2,3,[1,2,3],4,5,6]print(a的内存地址为,id(a))bcopy.deepcopy(a)print(b的内存地址为,id(b))b[3][1,1,3]print(修改b[0]的值后a的值为:,a)print(修改b的值后a的内存地址为,id(a))print(修改b[0]的值后b的值为:,b)print(修改b的值后b的内存地址为,id(b))a的内存地址为2329156546048b的内存地址为2329156546240修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为2329156546048修改b[0]的值后b的值为:[1,2,3,[1,1,3],4,5,6]修改b的值后b的内存地址为2329156546240#修改内部嵌套列表的其中一个元素只改变b不会改变aa[1,2,3,[1,2,3],4,5,6]print(a的内存地址为,id(a))bcopy.deepcopy(a)print(b的内存地址为,id(b))b[3][0]0print(修改b[0]的值后a的值为:,a)print(修改b的值后a的内存地址为,id(a))print(修改b[0]的值后b的值为:,b)print(修改b的值后b的内存地址为,id(b))a的内存地址为2344290446528b的内存地址为2344290446720修改b[0]的值后a的值为:[1,2,3,[1,2,3],4,5,6]修改b的值后a的内存地址为2344290446528修改b[0]的值后b的值为:[1,2,3,[0,2,3],4,5,6]修改b的值后b的内存地址为2344290446720总结引用直接复制所有元素不会放到新的存储空间浅拷贝只复制最外层的内部的嵌套数据共享存储空间深拷贝逐层递归复制所有数据都被放到一个新的存储空间

更多文章