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程序设计入门(2)变量类型简介
Jun 16 Python
python中异常报错处理方法汇总
Nov 20 Python
快速解决PyCharm无法引用matplotlib的问题
May 24 Python
python3使用SMTP发送简单文本邮件
Jun 19 Python
在python中按照特定顺序访问字典的方法详解
Dec 14 Python
对Python多线程读写文件加锁的实例详解
Jan 14 Python
pandas将多个dataframe以多个sheet的形式保存到一个excel文件中
Oct 10 Python
python日期与时间戳的各种转换示例
Feb 12 Python
Python 面向对象静态方法、类方法、属性方法知识点小结
Mar 09 Python
python regex库实例用法总结
Jan 03 Python
七个Python必备的GUI库
Apr 27 Python
浅谈Python协程asyncio
Jun 20 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 文件缓存函数
2011/10/08 PHP
PHP中基于ts与nts版本- vc6和vc9编译版本的区别详解
2013/04/26 PHP
单台服务器的PHP进程之间实现共享内存的方法
2014/06/13 PHP
thinkphp实现163、QQ邮箱收发邮件的方法
2015/12/18 PHP
php中文乱码问题的终极解决方案汇总
2017/08/01 PHP
PHP+swoole+linux实现系统监控和性能优化操作示例
2019/04/15 PHP
JS中剪贴板兼容性、判断复制成功或失败
2021/03/09 Javascript
拖动Html元素集合 Drag and Drop any item
2006/12/22 Javascript
Javascript 构造函数 实例分析
2008/11/26 Javascript
js 禁用只读文本框获得焦点时的退格键
2010/04/25 Javascript
Node.js 去掉种子(torrent)文件里的邪恶信息
2015/03/27 Javascript
跟我学习javascript的浮点数精度
2015/11/16 Javascript
javascript实现网页中涉及的简易运动(改变宽高、透明度、位置)
2015/11/29 Javascript
详解Angular2中的编程对象Observable
2016/09/17 Javascript
MUI 解决动态列表页图片懒加载再次加载不成功的bug问题
2017/04/13 Javascript
d3.js实现立体柱图的方法详解
2017/04/28 Javascript
vue如何获取点击事件源的方法
2017/08/10 Javascript
JavaScript时间戳与时间日期间相互转换
2017/12/11 Javascript
浅析微信扫码登录原理(小结)
2018/10/29 Javascript
基于JavaScript的数据结构队列动画实现示例解析
2020/08/06 Javascript
vue组件中传值EventBus的使用及注意事项说明
2020/11/16 Javascript
Python使用Selenium爬取淘宝异步加载的数据方法
2018/12/17 Python
python根据txt文本批量创建文件夹
2020/12/08 Python
使用Django搭建web服务器的例子(最最正确的方式)
2019/08/29 Python
Tensorflow获取张量Tensor的具体维数实例
2020/01/19 Python
Python列表list操作相关知识小结
2020/01/29 Python
英国第二大营养品供应商:Vitabiotics
2016/10/01 全球购物
医药专业推荐信
2013/11/15 职场文书
体育教育专业毕业生自荐信
2013/11/15 职场文书
竞争上岗演讲稿范文
2014/05/12 职场文书
毕业设计指导教师评语
2014/12/30 职场文书
毕业生班级鉴定评语
2015/01/04 职场文书
写给孩子的新学期寄语
2015/02/27 职场文书
2015年爱牙日活动总结
2015/03/23 职场文书
小学生勤俭节约倡议书
2015/04/29 职场文书
小学工作总结2015
2015/05/04 职场文书