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 tempfile模块学习笔记(临时文件)
May 25 Python
python进阶教程之循环相关函数range、enumerate、zip
Aug 30 Python
PyQt5打开文件对话框QFileDialog实例代码
Feb 07 Python
selenium+python自动化测试之鼠标和键盘事件
Jan 23 Python
python3使用matplotlib绘制散点图
Mar 19 Python
详解如何设置Python环境变量?
May 13 Python
在pytorch中为Module和Tensor指定GPU的例子
Aug 19 Python
在notepad++中实现直接运行python代码
Dec 18 Python
浅谈pytorch中的BN层的注意事项
Jun 23 Python
Pycharm-community-2020.2.3 社区版安装教程图文详解
Dec 08 Python
Python 数据科学 Matplotlib图库详解
Jul 07 Python
Python中with上下文管理协议的作用及用法
Mar 18 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
php实现的太平洋时间和北京时间互转的自定义函数分享
2014/08/19 PHP
PHP连接Nginx服务器并解析Nginx日志的方法
2015/08/16 PHP
php上传excel表格并获取数据
2017/04/27 PHP
JS支持带x身份证号码验证函数
2008/08/10 Javascript
capacityFixed 基于jquery的类似于新浪微博新消息提示的定位框
2011/05/24 Javascript
JS实现悬浮移动窗口(悬浮广告)的特效
2013/03/12 Javascript
热点新闻滚动特效的js代码
2013/08/17 Javascript
深入理解jQuery中live与bind方法的区别
2013/12/18 Javascript
js内置对象处理_打印学生成绩单的简单实现
2016/09/24 Javascript
js入门之Function函数的使用方法【新手必看】
2016/11/22 Javascript
Html中 IFrame的用法及注意点
2016/12/22 Javascript
深入理解 JavaScript 中的 JSON
2017/04/06 Javascript
二维码图片生成器QRCode.js简单介绍
2017/08/18 Javascript
JsChart组件使用详解
2018/03/04 Javascript
JavaScript引用类型Date常见用法实例分析
2018/08/08 Javascript
jQuery UI实现动画效果代码分享
2018/08/19 jQuery
jQuery+css last-child实现选择最后一个子元素操作示例
2018/12/10 jQuery
Vue 前端实现登陆拦截及axios 拦截器的使用
2019/07/17 Javascript
JavaScript this指向相关原理及实例解析
2020/07/10 Javascript
JavaScript TAB栏切换效果的示例
2020/11/05 Javascript
python解析基于xml格式的日志文件
2017/02/25 Python
Pandas探索之高性能函数eval和query解析
2017/10/28 Python
Python2.7基于笛卡尔积算法实现N个数组的排列组合运算示例
2017/11/23 Python
Python 面试中 8 个必考问题
2018/11/16 Python
使用Python-OpenCV向图片添加噪声的实现(高斯噪声、椒盐噪声)
2019/05/28 Python
pyqt5 tablewidget 利用线程动态刷新数据的方法
2019/06/17 Python
解决Jupyter notebook中.py与.ipynb文件的import问题
2020/04/21 Python
使用Python+Appuim 清理微信的方法
2021/01/26 Python
柏林通行证:Berlin Pass
2018/04/11 全球购物
家长给孩子的表扬信
2014/01/17 职场文书
教书育人演讲稿
2014/09/11 职场文书
公司领导班子召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
班主任工作实习计划
2015/01/16 职场文书
初中班长竞选稿
2015/11/20 职场文书
SQL注入篇学习之盲注/宽字节注入
2022/03/03 MySQL
Android开发EditText禁止输入监听及InputFilter字符过滤
2022/06/10 Java/Android