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编程中包的概念与管理
Oct 16 Python
Python实现的矩阵类实例
Aug 22 Python
Python爬虫爬取一个网页上的图片地址实例代码
Jan 16 Python
Python cookbook(数据结构与算法)字典相关计算问题示例
Feb 18 Python
将python代码和注释分离的方法
Apr 21 Python
opencv python 图像去噪的实现方法
Aug 31 Python
Python绘制并保存指定大小图像的方法
Jan 10 Python
如何在Django中设置定时任务的方法示例
Jan 18 Python
在python中用url_for构造URL的方法
Jul 25 Python
利用Python脚本批量生成SQL语句
Mar 04 Python
在django中使用post方法时,需要增加csrftoken的例子
Mar 13 Python
tensorflow pb to tflite 精度下降详解
May 25 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常量的详解
2013/06/09 PHP
Function eregi is deprecated (解决方法)
2013/06/21 PHP
PHP整合七牛实现上传文件
2015/07/03 PHP
php使用SAE原生Mail类实现各种类型邮件发送的方法
2016/10/10 PHP
用函数式编程技术编写优美的 JavaScript
2006/11/25 Javascript
JQuery开发的数独游戏代码
2010/10/29 Javascript
php图像生成函数之间的区别分析
2012/12/06 Javascript
js解析与序列化json数据(三)json的解析探讨
2013/02/01 Javascript
浏览器图片选择预览、旋转、批量上传的JS代码实现
2013/12/04 Javascript
JavaScript前补零操作实例
2015/03/11 Javascript
拥有一个属于自己的javascript表单验证插件
2016/03/24 Javascript
避免jQuery名字冲突 noConflict()方法
2016/07/30 Javascript
javascript实现瀑布流动态加载图片原理
2016/08/12 Javascript
Node.js查找当前目录下文件夹实例代码
2017/03/07 Javascript
解决AngualrJS页面刷新导致异常显示问题
2017/04/20 Javascript
jQuery插件FusionCharts绘制的3D双柱状图效果示例【附demo源码】
2017/04/20 jQuery
JS中Object对象的原型概念基础
2018/01/29 Javascript
babel的使用及安装配置教程
2018/02/22 Javascript
vue.js使用v-model指令实现的数据双向绑定功能示例
2018/05/22 Javascript
基于Vue 2.0 监听文本框内容变化及ref的使用说明介绍
2018/08/24 Javascript
JS数组去重的6种方法完整实例
2018/12/08 Javascript
Vue使用NProgress的操作过程解析
2019/10/10 Javascript
基于javascript处理二进制图片流过程详解
2020/06/08 Javascript
JS如何监听div的resize事件详解
2020/12/03 Javascript
python检测远程服务器tcp端口的方法
2015/03/14 Python
PyQt5每天必学之滑块控件QSlider
2018/04/20 Python
在PyCharm中控制台输出日志分层级分颜色显示的方法
2019/07/11 Python
Python远程linux执行命令实现
2020/11/11 Python
html5新增的属性和废除的属性简要概述
2013/02/20 HTML / CSS
Java里面有没有全局变量?为什么?
2015/02/06 面试题
生态养殖创业计划书
2014/05/06 职场文书
财务管理专业求职信
2014/06/11 职场文书
2014年党员自我评议(5篇)
2014/09/12 职场文书
党的群众路线教育实践活动个人对照检查材料(教师)
2014/11/04 职场文书
严以用权专题学习研讨会发言材料
2015/11/09 职场文书
2019年特色火锅店的创业计划书模板
2019/08/28 职场文书