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通过poll实现异步IO的方法
Jun 04 Python
python实现冒泡排序算法的两种方法
Mar 10 Python
用TensorFlow实现lasso回归和岭回归算法的示例
May 02 Python
python 脚本生成随机 字母 + 数字密码功能
May 26 Python
Python实现快速计算词频功能示例
Jun 25 Python
Python中关键字global和nonlocal的区别详解
Sep 03 Python
Python判断一个list中是否包含另一个list全部元素的方法分析
Dec 24 Python
python变量命名的7条建议
Jul 04 Python
Django 通过JS实现ajax过程详解
Jul 30 Python
python读写csv文件的方法
Aug 13 Python
python中strip(),lstrip(),rstrip()函数的使用讲解
Nov 17 Python
Python OpenCV超详细讲解调整大小与图像操作的实现
Apr 02 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读取html并截取字符串的简单代码
2009/11/30 PHP
PHP中对缓冲区的控制实现代码
2013/09/29 PHP
非常实用的php弹出错误警告函数扩展性强
2014/01/17 PHP
php检测useragent版本示例
2014/03/24 PHP
php版微信公众号自定义分享内容实现方法
2016/09/22 PHP
php curl获取到json对象并转成数组array的方法
2018/05/31 PHP
基于php伪静态的实现方法解析
2020/07/31 PHP
爱恋千雪-US-AscII加密解密工具(网页加密)下载
2007/06/06 Javascript
JavaScript 弹出窗体点击按钮返回选择数据的实现
2010/04/01 Javascript
jquery获取tr并更改tr内容示例代码
2014/02/13 Javascript
js中使用replace方法完成某个字符的转换
2014/08/20 Javascript
深入理解javascript严格模式(Strict Mode)
2014/11/28 Javascript
DOM基础教程之使用DOM设置文本框
2015/01/20 Javascript
html的DOM中Event对象onabort事件用法实例
2015/01/21 Javascript
jquery使用remove()方法删除指定class子元素
2015/03/26 Javascript
jQuery UI插件实现百度提词器效果
2016/11/21 Javascript
Vue数据驱动模拟实现4
2017/01/12 Javascript
详解Angular.js指令中scope类型的几种特殊情况
2017/02/21 Javascript
get  post jsonp三种数据交互形式实例详解
2017/08/25 Javascript
详解npm 配置项registry修改为淘宝镜像
2018/09/07 Javascript
Vue从TodoList中学父子组件通信
2019/02/05 Javascript
jQuery实现的隔行变色功能【案例】
2019/02/18 jQuery
three.js着色器材质的内置变量示例详解
2020/08/16 Javascript
antd form表单数据回显操作
2020/11/02 Javascript
详解Python中的array数组模块相关使用
2016/07/05 Python
python+tkinter实现学生管理系统
2019/08/20 Python
Python Unittest原理及基本使用方法
2020/11/06 Python
详解HTML5 Canvas绘制时指定颜色与透明度的方法
2016/03/25 HTML / CSS
印度最好的在线药品订购网站:PharmEasy
2018/11/30 全球购物
Groupon荷兰官方网站:高达70%的折扣
2019/11/01 全球购物
销售行政专员职责
2014/01/03 职场文书
校本教研工作制度
2014/01/22 职场文书
幼儿园小班教学反思
2014/02/02 职场文书
菜篮子工程实施方案
2014/03/08 职场文书
聚众斗殴罪辩护词
2015/05/21 职场文书
详解nginx.conf 中 root 目录设置问题
2021/04/01 Servers