详解Python直接赋值,深拷贝和浅拷贝


Posted in Python onJuly 09, 2020

直接赋值: 对象的引用,也就是给对象起别名
浅拷贝: 拷贝父对象,但是不会拷贝对象的内部的子对象。
深拷贝: 拷贝父对象. 以及其内部的子对象

在之前的文章中,提到可变对象和不可变对象,接下来也是以这两者的区别进行展开

直接赋值

对于可变对象和不可变对象,将一个变量直接赋值给另外一个变量,两者 id 值一致,其实本质上是将变量量绑定到对象的过程.

>>> a=1
>>> b=a
>>> id(a) == id(b)
True
>>> c="string"
>>> d=c
>>> id(c) == id(d)
True
>>> e=[1,2,3]
>>> f=e
>>> id(e)==id(f)
True

关于修改新变量的值,对原有变量会产生的影响,在可变对象和不可变对象 中也做了讲述,这里通过几个例子,重新温习一下

不可变对象

>>> x=1
>>> y=x
>>> id(x)==id(y)
True
>>> id(1)==id(y)
True
>>>>>> id(x)
1500143776
>>> y=y+1
>>> y
2
>>> x
1
>>> id(x)==id(y)
False
>>> id(y)
1500143808
>>> id(x)
1500143776

对于不可变对象,修改赋值后的新变量,不会对原有变量造成任何影响.为什么出现这种现象呢?因为不可变对象一旦创建之后就不允许被改变.后面对 y 进行的操作,其实是重新创建一个对象并绑定的结果:

详解Python直接赋值,深拷贝和浅拷贝

可变对象

>>> m=[1,2,3]
>>> n=m
>>> id(n)==id(m)
True
>>> id(m)
1772066764488
>>> id(n[0])
1772066764656
>>> n[0]=4
>>> n
[4, 2, 3]
>>> m
[4, 2, 3]
>>> id(n)==id(m)
True
>>> id(m)
1772066764488

对于可变对象,修改赋值后的变量,会对原有的变量造成影响,会导致其 value 值的改变,但是其id 值保持不变

详解Python直接赋值,深拷贝和浅拷贝

从上图不难看出,这个时候的 id(n[0]) 的值,和未修改前的 id值应该不一样,可以输出看一下

>>>id(n[0])
1772066764752 # 最初没有修改前是 1772066764656

n[0] 修改前后为什么 id 值出现改变呢? 首先需要明确一点 n[0] 绑定的是一个不可变对象,在文章的最初提到,不可变对象一旦创建就不允许修改.显然对 n[0] 进行修改,不能在绑定对象的内存上进行修改,那如何实现重新赋值呢?只能创建一个新的对象 4 ,然后将 n[0] 绑定到新的对象

浅拷贝和深拷贝

先看一下官方文档的定义

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or
class instances).
A shallow copy constructs a new compound object and then (to the
extent possible) inserts the same objects into it that the
original contains.
A deep copy constructs a new compound object and then, recursively,inserts copies into it of the objects found in the original.

从文档中不难看出,上面提到深拷贝和浅拷贝两者区别在于在复合对象,那接下来也只讨论复合对象.

浅拷贝

注意到官方文档也提到对浅拷贝和深拷贝的定义,从上文中不难看出,浅拷贝构建一个复合对象,然后将原有复合对象包含的对象插入到新的复合对象中

详解Python直接赋值,深拷贝和浅拷贝

从上图不难看出,浅拷贝后,新复合对象包含的对象(可变或者不可变)的 id 值和原有对象包含的对象的 id 值相同

看一下具体例子:

>>> import copy
>>> a=[1,2,[3,4]]
>>> b=copy.copy(a)
>>> id(b[0])==id(a[0])
True
>>> id(b[2])==id(a[2])
True
>>> id(b[2][0])==id(a[2][0])
True

现在让我们试着修改一下浅拷贝后的 b 的值,在修改前,可以先思考一下,如果修改 b[0] 可能会发生什么?

由于 b[0] = 1,很显然 1 属于不可变对象,那么根据对不可变变量修改的规则,则 b[0] 会绑定到新的变量上,而 a[0] 的由于没有修改,则保持不变,真的是这样吗?让我们验证一下

>>> b[0]=5
>>> b
[5, 2, [3, 4]]
>>> a
[1, 2, [3, 4]]

接下来我们要尝试修改一下 b[2],由于 b[2] 绑定的对象是 list,属于可变对象,按照上面说的可变对象修改的规则,则修改后的 b[2]id 值保持不变,但是其 value 值会发生改变. 同样的让我们通过例子验证一下

>>> id(b[2])
4300618568
>>> b[2][0]=6
>>> id(b[2])
4300618568
>>> b
[5, 2, [6, 4]]
>>> a
[1, 2, [6, 4]]

由于 b[2]a[2] 绑定同一个可变对象,很显然对 b[2] 的修改同样会映射到 a[2]

深拷贝

深拷贝构建一个复合对象,然后递归的将原有复合包含的对象的副本插入到新的复合对象中

详解Python直接赋值,深拷贝和浅拷贝

若上图所示,深拷贝后,新的复合对象包含的对象,若对象为不可变对象,则 id 值保持不变,若对象为可变对象,则 id 值发生改变

看一个例子:

>>> import copy
>>> a=[1,2,[3,4]]
>>> b=copy.deepcopy(a)
>>> id(b[0])==id(a[0])
True
>>> id(b[2])==id(a[0])
False
>>> id(b[2][0])==id(a[2][0])
True

接下来让我们修改一下变量 b,这里就不在修改不可变对象 b[0]b[1] 了,因为结果很明显,对 a 不会产生任何影响,我们来修改 b[2],那么修改 b[2] 会对 a[2] 产生影响吗?很明显答案是不会,因为深拷贝就相当于克隆出了一个全新的个体,两者不再有任何关系

>>> b[2][0]=5
>>> b
[1, 2, [5, 4]]
>>> a
[1, 2, [3, 4]]

以上就是详解Python直接赋值,深拷贝和浅拷贝的详细内容,更多关于Python直接赋值,深拷贝和浅拷贝的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
本地文件上传到七牛云服务器示例(七牛云存储)
Jan 11 Python
Python基础篇之初识Python必看攻略
Jun 23 Python
python WindowsError的错误代码详解
Jul 23 Python
python使用super()出现错误解决办法
Aug 14 Python
python 处理telnet返回的More,以及get想要的那个参数方法
Feb 14 Python
Python简易版图书管理系统
Aug 12 Python
Python全栈之列表数据类型详解
Oct 01 Python
python通过安装itchat包实现微信自动回复收到的春节祝福
Jan 19 Python
Python判断三段线能否构成三角形的代码
Apr 12 Python
关于Keras Dense层整理
May 21 Python
python+playwright微软自动化工具的使用
Feb 02 Python
Python+Selenium实现抖音、快手、B站、小红书、微视、百度好看视频、西瓜视频、微信视频号、搜狐视频、一点号、大风号、趣头条等短视频自动发布
Apr 13 Python
使用python实现下载我们想听的歌曲,速度超快
Jul 09 #Python
Python selenium模块实现定位过程解析
Jul 09 #Python
Python自动化操作实现图例绘制
Jul 09 #Python
解决pip install psycopg2出错问题
Jul 09 #Python
利用python下载scihub成文献为PDF操作
Jul 09 #Python
Python scrapy爬取小说代码案例详解
Jul 09 #Python
使用Python实现微信拍一拍功能的思路代码
Jul 09 #Python
You might like
中篇:安装及配置PHP
2006/12/13 PHP
PHP MYSQL乱码问题,使用SET NAMES utf8校正
2009/11/30 PHP
php导入导出excel实例
2013/10/25 PHP
配置Nginx+PHP的正确思路与过程
2016/05/10 PHP
php实现文件与16进制相互转换的方法示例
2017/02/16 PHP
php双层循环(九九乘法表)
2017/10/23 PHP
jQuery自带的一些常用方法总结
2014/09/03 Javascript
浅谈JavaScript 框架分类
2014/11/10 Javascript
jquery渐隐渐显的图片幻灯闪烁切换实现方法
2015/02/26 Javascript
JavaScript实现点击自动选择TextArea文本的方法
2015/07/02 Javascript
Jquery+Ajax+PHP+MySQL实现分类列表管理(下)
2015/10/28 Javascript
JavaScript学习总结之JS、AJAX应用
2016/01/29 Javascript
AngularJS双向绑定和依赖反转实例详解
2017/04/15 Javascript
微信小程序 空白页重定向解决办法
2017/06/27 Javascript
vue 动态表单开发方法案例详解
2019/12/02 Javascript
开发Node CLI构建微信小程序脚手架的示例
2020/03/27 Javascript
vue 解决addRoutes多次添加路由重复的操作
2020/08/04 Javascript
[01:09:20]NB vs NAVI Supermajor小组赛A组 BO3 第二场 6.2
2018/06/03 DOTA
Pyramid Mako模板引入helper对象的步骤方法
2013/11/27 Python
python3使用urllib模块制作网络爬虫
2016/04/08 Python
python面向对象法实现图书管理系统
2019/04/19 Python
OpenCV-Python 摄像头实时检测人脸代码实例
2019/04/30 Python
pandas 数据索引与选取的实现方法
2019/06/21 Python
在Django下创建项目以及设置settings.py教程
2019/12/03 Python
django框架forms组件用法实例详解
2019/12/10 Python
python 图像判断,清晰度(明暗),彩色与黑白实例
2020/06/04 Python
python绘图pyecharts+pandas的使用详解
2020/12/13 Python
全球领先的中国制造商品在线批发平台:DHgate
2020/01/28 全球购物
意大利买卖二手奢侈品网站:LAMPOO
2020/06/03 全球购物
写一个在SQL Server创建表的SQL语句
2012/03/10 面试题
旅游管理专业学生求职信
2013/09/28 职场文书
一名女生的自荐信
2013/12/08 职场文书
5.12护士节演讲稿
2014/04/30 职场文书
党校毕业心得体会
2014/09/13 职场文书
教师政风行风评议心得体会
2014/10/21 职场文书
vue实现可拖拽的dialog弹框
2021/05/13 Vue.js