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的身份证号码自动生成程序
Aug 15 Python
讲解Python中的递归函数
Apr 27 Python
在Django中限制已登录用户的访问的方法
Jul 23 Python
Python中str is not callable问题详解及解决办法
Feb 10 Python
python在非root权限下的安装方法
Jan 23 Python
为什么选择python编程语言入门黑客攻防 给你几个理由!
Feb 02 Python
用Python识别人脸,人种等各种信息
Jul 15 Python
flask/django 动态查询表结构相同表名不同数据的Model实现方法
Aug 29 Python
python+mysql实现个人论文管理系统
Oct 25 Python
python实现简单日志记录库glog的使用
Dec 13 Python
Python 实现 T00ls 自动签到脚本代码(邮件+钉钉通知)
Jul 06 Python
使用Python爬虫爬取小红书完完整整的全过程
Jan 19 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
Ajax+PHP 边学边练 之二 实例
2009/11/24 PHP
PHP中多维数组的foreach遍历示例
2014/06/13 PHP
bindParam和bindValue的区别以及在Yii2中的使用详解
2018/03/12 PHP
基于jsTree的无限级树JSON数据的转换代码
2010/07/27 Javascript
纯js网页画板(Graphics)类简介及实现代码
2012/12/24 Javascript
jquery 多行文本框(textarea)高度变化
2013/07/03 Javascript
jquery简单的拖动效果实现原理及示例
2013/07/26 Javascript
关于jQuery中.attr()和.prop()的问题探讨
2013/09/06 Javascript
js函数定时器实现定时读取系统实时连接数
2014/04/30 Javascript
简单的jquery左侧导航栏和页面选中效果
2014/08/21 Javascript
js日期范围初始化得到前一个月日期的方法
2015/05/05 Javascript
浅谈vuex 闲置状态重置方案
2018/01/04 Javascript
vue中Axios的封装与API接口的管理详解
2018/08/09 Javascript
浅谈Vue服务端渲染框架Nuxt的那些事
2018/12/21 Javascript
Vue表单控件绑定图文详解
2019/02/11 Javascript
vue通过video.js解决m3u8视频播放格式的方法
2019/07/30 Javascript
JavaScript在web自动化测试中的作用示例详解
2019/08/25 Javascript
在Koa.js中实现文件上传的接口功能
2019/10/08 Javascript
vue登录以及权限验证相关的实现
2019/10/25 Javascript
JS实现滑动导航效果
2020/01/14 Javascript
python机器学习之随机森林(七)
2018/03/26 Python
Python实现随机生成手机号及正则验证手机号的方法
2018/04/25 Python
在Python中通过getattr获取对象引用的方法
2019/01/21 Python
Python2与Python3的区别实例分析
2019/04/11 Python
Python中一个for循环循环多个变量的示例
2019/07/16 Python
vue常用指令代码实例总结
2020/03/16 Python
哈工大自然语言处理工具箱之ltp在windows10下的安装使用教程
2020/05/07 Python
美国知名的百货清仓店:Neiman Marcus Last Call
2016/08/03 全球购物
找到不普通的东西:Bonanza
2016/10/20 全球购物
德国运动鞋网上商店:Afew Store
2018/01/05 全球购物
Annoushka英国官网:英国奢侈珠宝品牌
2018/10/20 全球购物
公司证明怎么写
2014/09/22 职场文书
房屋租赁合同补充协议
2014/10/11 职场文书
nginx限制并发连接请求数的方法
2021/04/01 Servers
Python获取百度热搜的完整代码
2021/04/07 Python
Go本地测试解耦任务拆解及沟通详解Go本地测试的思路沟通的重要性总结
2022/06/21 Golang