Python的赋值、深拷贝与浅拷贝的区别详解


Posted in Python onFebruary 12, 2020

在python中,给一个对象赋值,实际上就是对象对内存空间存储的值的引用。当我们把对象赋值给另一个变量的时候,这个变量并没有拷贝这个对象,而只是拷贝了这个对象的引用而已。

一般情况下我们会通过三种方法来实现拷贝对象的引用。

Python直接赋值

直接赋值,默认浅拷贝传递对象的引用而已,原始列表改变,被赋值的变量也会做相同的改变。其实就是对‘对象'的引用

示例:

>>> list_demo = [2, 4, 6]
>>> a = list_demo
>>> print(a)
[2, 4, 6]
>>> id(list_demo)
65006808
>>> id(a)
65006808
>>> list_demo.append(8)
>>> print(list_demo)
[2, 4, 6, 8]
>>> print(a)
[2, 4, 6, 8]
>>> id(list_demo)
65006808
>>> id(a)
65006808
>>>

通过 id() 函数我们可以得出,变量 list_demo 与 a 指向的都是同一个内存空间地址,当被赋值的 list_demo改变,被赋值的 a 同样会做相同的改变。这种现象普遍存在于 Python 之中,这种赋值的方式实现了 “假装” 拷贝,真实的情况还是两个变量和同一个对象之间的引用关系。

Python浅拷贝

import copy 模块的 copy.copy() 方法,该方法只拷贝父对象,没有拷贝子对象。且浅拷贝是创建一块新的内存空间,但是内存空间内的元素的地址均是父对象元素的地址的拷贝。所以当父对象内部的子对象发生改变时,拷贝对象的内部的子对象也会跟着改变。

示例:

>>> list_demo1 = [2, 4, 6, [8, 10]]
>>> a = list_demo1
>>> print(list_demo1)
[2, 4, 6, [8, 10]]
>>> print(a)
[2, 4, 6, [8, 10]]
>>>
>>>
>>> import copy
>>> b = copy.copy(list_demo1)
>>> id(list_demo1)
65103472
>>> id(b)
6011200
>>> list_demo1.append(12)
>>> print(list_demo1)
[2, 4, 6, [8, 10], 12]
>>> list_demo1[3]
[8, 10]
>>>
>>>
>>>
>>> list_demo1[3].append('hello')
>>> print(list_demo1)
[2, 4, 6, [8, 10, 'hello'], 12]
>>> print(b)
[2, 4, 6, [8, 10, 'hello']]
>>> list_demo1[3]
[8, 10, 'hello']
>>> b[3]
[8, 10, 'hello']
>>>
>>>
>>>
>>> id(list_demo1)
65103472
>>> id(b)
6011200
>>> id(list_demo1[3])
64679128
>>> id(b[3])
64679128
>>>

从上述代码可以看出,在执行浅拷贝的时候,浅拷贝实际上只拷贝引用,不拷贝内容。同时,浅拷贝会针对父对象的子对象进行判断,当父对象的子对象发生改变时,拷贝对象内的子对象同时也跟着改变。

Python深拷贝

import copy 模块的 copy.deepcopy() 方法,深拷贝与浅拷贝相反,就是彻彻底底的拷贝,完全的拷贝了父对象及子对象,同时指向一个新的内存空间地址。此时,虽然源对象与拷贝对象的内容是一样的,但是不管针对谁进行改动,另一个是丝毫不会受到影响的。

>>> list_demo2 = [2,3,4]

>>> c= copy.deepcopy(list_demo2)

>>> print(list_demo2)

[2, 3, 4]

>>> print(c)

[2, 3, 4]

>>> id(list_demo2)

6011440

>>> id(c)

6012440

>>> list_demo2.append(['a','b'])

>>> c.append([5,6])

>>> print(list_demo2)

[2, 3, 4, ['a', 'b']]

>>> print(c)

[2, 3, 4, [5, 6]]

>>> list_demo2[3].append('c')

>>> c[3].append(7)

>>> print(list_demo2)

[2, 3, 4, ['a', 'b', 'c']]

>>> print(c)

[2, 3, 4, [5, 6, 7]]

>>>

从上述代码示例可以看出 list_demo2 与 c 相互独立,无论 list_demo2 与 c本身进行了修改,或者各自的子对象进行了修改 都没有互相影响。

总结

Python赋值

赋值的本质就是将一个对象的内存空间地址赋值给一个变量,让变量指向该内存空间地址。

Python浅拷贝

浅拷贝是拷贝了源对象的引用,并创建了一个新的内存空间地址。但是引用的对象的子对象的地址仍然是源对象的,所以当源对象的子对象发生改变时,拷贝对象内的子对象同时也跟着改变。

Python深拷贝

深拷贝就是彻底的拷贝,完全的拷贝了父对象及子对象,同时指向一个新的内存空间地址。源对象与拷贝对象之间的修改互不影响。

更多关于Python的赋值、深拷贝与浅拷贝的区别文章请查看下面的相关链接

Python 相关文章推荐
python计算方程式根的方法
May 07 Python
Python实现简单求解给定整数的质因数算法示例
Mar 25 Python
python实时监控cpu小工具
Jun 21 Python
APIStar:一个专为Python3设计的API框架
Sep 26 Python
使用celery执行Django串行异步任务的方法步骤
Jun 06 Python
对Python强大的可变参数传递机制详解
Jun 13 Python
python中如何使用insert函数
Jan 09 Python
Python切割图片成九宫格的示例代码
Mar 10 Python
在PyTorch中使用标签平滑正则化的问题
Apr 03 Python
音频处理 windows10下python三方库librosa安装教程
Jun 20 Python
Django --Xadmin 判断登录者身份实例
Jul 03 Python
Python利用命名空间解析XML文档
Aug 10 Python
解决pyCharm中 module 调用失败的问题
Feb 12 #Python
Python写出新冠状病毒确诊人数地图的方法
Feb 12 #Python
pycharm通过ssh连接远程服务器教程
Feb 12 #Python
python日期与时间戳的各种转换示例
Feb 12 #Python
Python使用uuid库生成唯一标识ID
Feb 12 #Python
将python文件打包exe独立运行程序方法详解
Feb 12 #Python
Python打包模块wheel的使用方法与将python包发布到PyPI的方法详解
Feb 12 #Python
You might like
dede全站URL静态化改造[070414更正]
2007/04/17 PHP
PHP中数组的分组排序实例
2014/06/01 PHP
PHP中include和require的区别实例分析
2017/05/07 PHP
PHP8.0新功能之Match表达式的使用
2020/07/19 PHP
javascript 获取页面的高度及滚动条的位置的代码
2010/05/06 Javascript
修改jquery里的dialog对话框插件为框架页(iframe) 的方法
2010/09/14 Javascript
JS面向对象编程 for Cookie
2010/09/19 Javascript
Javascript前端UI框架Kit使用指南之kitjs的对话框组件
2014/11/28 Javascript
javascript实现在线客服效果
2015/07/15 Javascript
jquery实现的伪分页效果代码
2015/10/29 Javascript
不间断循环滚动效果的实例代码(必看篇)
2016/10/08 Javascript
js格式化时间的简单实例
2016/11/27 Javascript
详解使用fetch发送post请求时的参数处理
2017/04/05 Javascript
axios进阶实践之利用最优雅的方式写ajax请求
2017/12/20 Javascript
Three.JS实现三维场景
2018/12/30 Javascript
详解vue.js移动端配置flexible.js及注意事项
2019/04/10 Javascript
Node.js+ELK日志规范的实现
2019/05/23 Javascript
浅谈一个webpack构建速度优化误区
2019/06/24 Javascript
vue实现pdf文档在线预览功能
2019/11/26 Javascript
[06:37]2014DOTA2国际邀请赛 昔日王者渴望重回巅峰
2014/07/12 DOTA
使用Kivy将python程序打包为apk文件
2017/07/29 Python
Python中static相关知识小结
2018/01/02 Python
解决Python找不到ssl模块问题 No module named _ssl的方法
2019/04/29 Python
python错误调试及单元文档测试过程解析
2019/12/19 Python
亚马逊巴西站:Amazon.com.br
2019/09/22 全球购物
大学生毕业自我鉴定
2013/11/06 职场文书
计算机求职信
2013/12/01 职场文书
普通党员个人整改措施
2014/10/27 职场文书
环卫工作汇报材料
2014/10/28 职场文书
内乡县衙导游词
2015/02/05 职场文书
2015年街道办事处团委工作总结
2015/10/14 职场文书
职场:企业印章管理制度(模板)
2019/10/18 职场文书
Vue CLI中模式与环境变量的深入详解
2021/05/30 Vue.js
Nginx使用Lua模块实现WAF的原理解析
2021/09/04 Servers
Python如何使用循环结构和分支结构
2022/04/13 Python
超越Nginx的Web服务器caddy优雅用法
2022/06/21 Servers