Python 深浅拷贝

一、赋值

前面说过,一个对象有 id、type、value 三个要素,变量名通过引用 id 的方式去找到一个对象(类似于文件名通过 inode 找到具体数据块,只有 id 能唯一标识一个对象)。

在这里插入图片描述

而用一个变量赋值给令一个变量,就相当于这两个变量共享了这个引用(有点像硬链接)

在这里插入图片描述
如果删除掉 a 之后,并不会影响 b 的引用

在这里插入图片描述

在不可变数据类型中这是没问题的,变量每次重新赋值都会将其引用改成新对象的地址

在这里插入图片描述
但是在可变数据类型中,这就会出问题

在这里插入图片描述
原因是 a 和 b 共享了同一个列表的引用,而列表是可变类型对象,改变列表中的值列表的 id 并不会改变(列表的 value 事实上就是一个个对象 id 的引用,所以对应 value 的值会变)

拷贝概念的引入就是针对可变对象的共享引用潜在的副作用而提出的

二、浅拷贝

如果不想改变 b 的值,就要使用 copy 模块或使用切片

在这里插入图片描述
可以看到,由于 a、b、c 三个变量引用了不同的列表对象,对列表中的元素改变并不会影响其他两个列表

但这还是有问题的

在这里插入图片描述
原因是虽然使用浅拷贝时在内存中新开辟了一块空间存放一个新列表,但列表中的 value 并没有变

在这里插入图片描述
而这三个列表最后一个元素又是一个列表,是可变类型的对象,改变其元素的值并不会改变其地址

浅拷贝就相当于重新为列表中的元素做了一个”“,列表中存放的元素(value)并没有发生变化,变的是列表的 id

在这里插入图片描述
要解决这种问题,就要使用深拷贝

三、深拷贝

在深拷贝中,不仅列表的这个”“会变,列表中要是有其他可变类型的数据,它们也会被重新开辟一块内存空间来存放

在这里插入图片描述
可以看到,改变 a[-1] 的值并不会改变影响深拷贝出来的列表,而切片出来的列表被改变了

可以看到切片前后元素的 id 并没有发生变化,这就可以说明:切片和浅拷贝是等效的

事实上,要理解深拷贝,应该是这样的:深拷贝会递归的将列表中每一个元素都重新生成一次在这里插入图片描述
但是在 Python 中对这个过程进行了优化,如果列表中的元素是不可变类型的话,深拷贝会将这些对象复用,并不会重新为它们开辟一块空间赋值(大概是因为对引用不可变类型的对象赋值会更改其引用),就成了下图

在这里插入图片描述

四、总结

  1. 赋值是对引用的共享
  2. 浅拷贝和切片的效果相同,浅拷贝一个可变类型对象会开辟一个新的空间,但对象中的值是不会发生变化的
  3. 深拷贝会递归的对可变类型对象中的所有元素继续深拷贝
  4. Python 中对拷贝做了优化,不可改变类型对象的拷贝并不会开辟新空间,仍是共享引用

深浅copy

Python中的深浅拷贝详解

python之深浅拷贝

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值