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随机生成一个6位的验证码代码分享
Mar 24 Python
详解JavaScript编程中的window与window.screen对象
Oct 26 Python
Python操作RabbitMQ服务器实现消息队列的路由功能
Jun 29 Python
python装饰器实例大详解
Oct 25 Python
Python内存读写操作示例
Jul 18 Python
Python连接Redis的基本配置方法
Sep 13 Python
Python3使用Matplotlib 绘制精美的数学函数图形
Apr 11 Python
Python实现二叉树的最小深度的两种方法
Sep 30 Python
使用pickle存储数据dump 和 load实例讲解
Dec 30 Python
Python xlrd excel文件操作代码实例
Mar 10 Python
Python标准库shutil模块使用方法解析
Mar 10 Python
在python中使用pyspark读写Hive数据操作
Jun 06 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源代码加密?PHP二进制加密与解密的解决办法
2013/04/22 PHP
php颜色转换函数hex-rgb(将十六进制格式转成十进制格式)
2013/09/23 PHP
PHP实现股票趋势图和柱形图
2015/02/07 PHP
javascript 网页跳转的方法
2008/12/24 Javascript
FireFox JavaScript全局Event对象
2009/06/14 Javascript
基于jquery的表格排序
2010/09/11 Javascript
Javascript在IE下设置innerHTML时出现未知的运行时错误的解决方法
2011/01/12 Javascript
JQuery对表单元素的基本操作使用总结
2014/07/18 Javascript
浅析Node在构建超媒体API中的作用
2014/07/30 Javascript
jQuery源码解读之removeAttr()方法分析
2015/02/20 Javascript
论Bootstrap3和Foundation5网格系统的异同
2016/05/16 Javascript
Jquery uploadify 多余的Get请求(404错误)的解决方法
2017/01/26 Javascript
ES6中module模块化开发实例浅析
2017/04/06 Javascript
详解nodejs微信公众号开发——4.自动回复各种消息
2017/04/11 NodeJs
bootstrap时间插件daterangepicker使用详解
2017/10/19 Javascript
jQuery 点击获取验证码按钮及倒计时功能
2018/09/20 jQuery
html-webpack-plugin修改页面的title的方法
2020/06/18 Javascript
解决vue中的无限循环问题
2020/07/27 Javascript
javascript实现京东登录显示隐藏密码
2020/08/02 Javascript
11个Javascript小技巧帮你提升代码质量(小结)
2020/12/28 Javascript
Python中的startswith和endswith函数使用实例
2014/08/25 Python
Python使用multiprocessing创建进程的方法
2015/06/04 Python
利用Python学习RabbitMQ消息队列
2015/11/30 Python
详解如何用OpenCV + Python 实现人脸识别
2017/10/20 Python
Python实现简单网页图片抓取完整代码实例
2017/12/15 Python
利用Python模拟登录pastebin.com的实现方法
2019/07/12 Python
Python安装selenium包详细过程
2019/07/23 Python
迪士尼法国在线商店:shopDisney FR
2020/12/03 全球购物
关于人生的感言
2014/01/17 职场文书
公司中秋节活动方案
2014/02/12 职场文书
社区活动总结报告
2014/05/05 职场文书
年度评优评先方案
2014/06/03 职场文书
竞选班干部演讲稿500字
2014/08/20 职场文书
英文升职感谢信
2015/01/23 职场文书
党员个人总结自评
2015/02/14 职场文书
Nginx URL重写rewrite机制原理及使用实例
2021/04/01 Servers