python的深拷贝与浅拷贝

python的深拷贝与浅拷贝

引言

前两天在用python写A*算法的时候,被python的深拷贝和浅拷贝恶搞了一番,实际上还是因为没搞清楚哪些是深拷贝,哪些是浅拷贝,现特意写一篇小结,加深理解。

什么是浅拷贝

所谓浅拷贝,就是复制了地址,实质上是产生了一个指针,指向与之前内容相同的内存块
eg:
在这里插入图片描述
可以清楚的看到,b和a指向的是同一块内容,改变b的值,a的值也将随着改变

什么是深拷贝

所谓深拷贝,就是产生了新的地址、申请了新的内存来储存拷贝物
eg:
在这里插入图片描述
可以清楚的看到,b复制了a的内容,但是并没有复制a的地址,改变b的值并不会影响a的值

为什么要区分浅拷贝和深拷贝

这就是一个蛋疼的问题了。以我写此文的契机来举例,Astar算法:
Astar算法是一种启发式搜索算法,以八数码问题为例
在这里插入图片描述
数字0表示的是空位,其他数字位要一步一步移动成目标态。
算法是这样的:通过移动空位,让初态变成目标态。也就是,通过0和上下左右分别交换,进入下一个状态。具体Astar算法怎样实现,大家有兴趣的话可以搜搜别人的文章,被写烂了。
这里就会出现一个深拷贝和浅拷贝的问题,必须深拷贝一个当前状态的3*3矩阵,再进行移动;
可以这样理解:一个状态要向四个方向移动,得到四个子状态,如果采用浅拷贝,那在向上移动的时候,父矩阵也会跟着改变,变成向上移动;你想要再向下、左、右移动的时候就得不到想要的解了。

python中哪些数据结构是默认深拷贝的

一般而言,非容器类型,int、float、str等,都是浅拷贝,因为开销小所以py默认这些数据结构为深拷贝

python中哪些数据结构是默认浅拷贝的

相反的,list、tuple、dirc、set等容器类型的数据结构,因为深拷贝开销大,所以默认都是浅拷贝的。
在这里插入图片描述
列表

----------------------

在这里插入图片描述
元祖(元祖的元素是不允许被修改的)

-----------------------

在这里插入图片描述
字典

-----------------------

在这里插入图片描述
集合(集合元素不允许重复)

浅拷贝元素怎么进行深拷贝呢?

介绍一个内置函数,叫.copy()
在这里插入图片描述
你看你看~惊不惊喜,意不意外
需要注意的是,元祖没有这个内置函数,列表、集合、字典都有
通过.copy()这个函数,就可以对数据进行深拷贝

为你哭,为你笑,为你抓狂为你闹

你以为就这点深拷贝浅拷贝知识我会被绕弯?不!你错了,下面来看我真正被绕死的例子
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200326170221542.png
提问,b=a.copy()完成了对a的深拷贝吗?
张三:真的有点猛,这不是明摆着吗,id都不一样了
是的,对于这个长度为3的列表,a[0]、a[1]、a[2]都完成了深拷贝,但是!重点来了,这个列表的第0个元素是不是一个三维的列表啊?每一维都是一个新的列表,那么,对于这个三维列表里面的每一维,进行的是深拷贝还是浅拷贝?
在这里插入图片描述
???惊不惊喜,意不意外,我都用了copy了他*的进行的还是浅拷贝!
可以这样理解,copy是用了一个for,扫了一遍每个元素,然后申请了一块新的内存给每个元素
但是,a[0]原本装的就是个指针,指向[[1],[2],[3],[4]],就算申请了新的内存,也不是为实体申请的,而是为指针申请的,用一个新的内存,装了一个旧指针,指向的当然还是旧内容。
对于这种嵌套的容器,他嵌套你也嵌套啊!
在这里插入图片描述
用这样一个for循环,扫上面白图的a0,还怕你不深拷贝?

结束语

好,俺终于写完了,俺不是鸽子了

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值