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 相关文章推荐
wxPython窗口的继承机制实例分析
Sep 28 Python
Python入门篇之数字
Oct 20 Python
python通过colorama模块在控制台输出彩色文字的方法
Mar 19 Python
在Python中使用poplib模块收取邮件的教程
Apr 29 Python
Python随机生成数据后插入到PostgreSQL
Jul 28 Python
Flask框架响应、调度方法和蓝图操作实例分析
Jul 24 Python
Django命名URL和反向解析URL实现解析
Aug 09 Python
python实现单链表的方法示例
Sep 03 Python
pytorch实现onehot编码转为普通label标签
Jan 02 Python
Python3爬虫里关于代理的设置总结
Jul 30 Python
python try...finally...的实现方法
Nov 25 Python
Jupyter notebook 更改文件打开的默认路径操作
May 21 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邮件管理器源码
2016/01/06 PHP
PHP基于反射机制实现插件的可插拔设计详解
2016/11/10 PHP
php数组实现根据某个键值将相同键值合并生成新二维数组的方法
2017/04/26 PHP
Js动态创建div
2008/09/25 Javascript
javascript实现页面内关键词高亮显示代码
2014/04/03 Javascript
详解AngularJS中的http拦截
2016/02/09 Javascript
JS实现获取当前URL和来源URL的方法
2016/08/24 Javascript
Angularjs 实现分页功能及示例代码
2016/09/14 Javascript
JavaScript中关于iframe滚动条的去除和保留
2016/11/17 Javascript
vue父子组件的嵌套的示例代码
2017/09/08 Javascript
Angular 数据请求的实现方法
2018/05/07 Javascript
ES6之模版字符串的具体使用
2018/05/17 Javascript
微信小程序常见页面跳转操作简单示例
2019/05/01 Javascript
图解javascript作用域链
2019/05/27 Javascript
jquery ui 实现 tab标签功能示例【测试可用】
2019/07/25 jQuery
基于jquery ajax的多文件上传进度条过程解析
2019/09/11 jQuery
小程序实现长按保存图片的方法
2019/12/31 Javascript
python zip文件 压缩
2008/12/24 Python
python通过cookie模拟已登录状态的初步研究
2016/11/09 Python
使用requests库制作Python爬虫
2018/03/25 Python
可能是最全面的 Python 字符串拼接总结【收藏】
2018/07/09 Python
神经网络相关之基础概念的讲解
2018/12/29 Python
详解DeBug Python神级工具PySnooper
2019/07/03 Python
Django 路由控制的实现
2019/07/17 Python
python爬虫增加访问量的方法
2019/08/22 Python
Python中zip()函数的简单用法举例
2019/09/02 Python
pyCharm 设置调试输出窗口中文显示方式(字符码转换)
2020/06/09 Python
UGG雪地靴荷兰官网:UGG荷兰
2016/09/09 全球购物
乌克兰的第一家手表店:Deka
2020/03/05 全球购物
枚举和一组预处理的#define有什么不同
2016/09/21 面试题
工商学院毕业生自荐信
2013/11/12 职场文书
酒店前台接待岗位职责
2013/12/03 职场文书
科研课题实施方案
2014/03/18 职场文书
优秀团员自我评价范文
2014/04/23 职场文书
仲裁协议书
2014/09/26 职场文书
小学生禁毒教育心得体会
2016/01/15 职场文书