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 相关文章推荐
ssh批量登录并执行命令的python实现代码
May 25 Python
跟老齐学Python之眼花缭乱的运算符
Sep 14 Python
Python基于sftp及rsa密匙实现远程拷贝文件的方法
Sep 21 Python
python fabric实现远程部署
Jan 05 Python
python中urllib.unquote乱码的原因与解决方法
Apr 24 Python
Python中的单继承与多继承实例分析
May 10 Python
Pytorch实现各种2d卷积示例
Dec 30 Python
Python Selenium 设置元素等待的三种方式
Mar 18 Python
使用python实现CGI环境搭建过程解析
Apr 28 Python
详解python metaclass(元类)
Aug 13 Python
Python-OpenCV实现图像缺陷检测的实例
Jun 11 Python
使用pipenv管理python虚拟环境的全过程
Sep 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中__FILE__、dirname与basename用法实例分析
2014/12/01 PHP
对laravel in 查询的使用方法详解
2019/10/09 PHP
JavaScript While 循环基础教程
2007/04/05 Javascript
实现JavaScript中继承的三种方式
2009/10/16 Javascript
javascript 事件处理程序介绍
2012/06/27 Javascript
JS控制阿拉伯数字转为中文大写示例代码
2013/09/04 Javascript
Jquery判断radio、selelct、checkbox是否选中及获取选中值方法总结
2015/04/15 Javascript
jquery验证邮箱格式是否正确实例讲解
2015/11/16 Javascript
使用Web Uploader实现多文件上传
2016/06/08 Javascript
Vue.js第一天学习笔记(数据的双向绑定、常用指令)
2016/12/01 Javascript
React进阶学习之组件的解耦之道
2017/08/07 Javascript
vue使用jsonp抓取qq音乐数据的方法
2018/06/21 Javascript
在iFrame子页面里实现模态框的方法
2018/08/17 Javascript
详解如何用VUE写一个多用模态框组件模版
2018/09/27 Javascript
Vue.js 父子组件通信的十种方式
2018/10/30 Javascript
详解Vue中的watch和computed
2020/11/09 Javascript
讲解python参数和作用域的使用
2013/11/01 Python
Python中多线程及程序锁浅析
2015/01/21 Python
使用Python中的greenlet包实现并发编程的入门教程
2015/04/16 Python
详解Python3中yield生成器的用法
2015/08/20 Python
python批量复制图片到另一个文件夹
2018/09/17 Python
python文件写入write()的操作
2019/05/14 Python
Python3 批量扫描端口的例子
2019/07/25 Python
浅谈python已知元素,获取元素索引(numpy,pandas)
2019/11/26 Python
Python reversed函数及使用方法解析
2020/03/17 Python
使用TensorBoard进行超参数优化的实现
2020/07/06 Python
Pytorch自定义Dataset和DataLoader去除不存在和空数据的操作
2021/03/03 Python
利用CSS3实现动态的二级三级菜单效果实例源码
2017/01/04 HTML / CSS
纯CSS实现聊天框小尖角、气泡效果
2014/04/04 HTML / CSS
HTML5中使用json对象的实例代码
2018/09/10 HTML / CSS
竞聘书模板
2014/03/31 职场文书
地震捐款倡议书
2014/08/29 职场文书
社区党建工作汇报材料
2014/10/27 职场文书
街道党风廉政建设调研报告
2015/01/01 职场文书
同意报考公务员证明
2015/06/17 职场文书
详解flex:1什么意思
2022/07/23 HTML / CSS