IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python篇 深拷贝与浅拷贝 -> 正文阅读

[Python知识库]python篇 深拷贝与浅拷贝

1.拷贝概念

如果各位捧场的读者老爷对python中‘’is‘’和‘’==‘’运算符的概念如我一样有些许了解的话,那应该知道当我们在将一个变量赋予另一个变量如“a = b ”时,如果b的值在小整型缓存区(-5~256)内,那么所谓的将b值赋值给a就只是引用同一个内存数据罢了。深拷贝浅拷贝有点类似于这个,“浅”字在这里的意思就是浅浅一层,仅能能拷贝对象的表层,而其子对象,就是直接拿来引用了,所谓深拷贝就是用递归的原理把其子对象也依次拷贝下来,这就是两者的区别。

百般口舌不如一证,下面举些小例子用以说明,如果基础较差的读者可以按情况点击下面链接查看笔记。

1.2 相关知识点

python篇 “is"和”=="
python篇 变量应用
python篇 面向对象

2.浅拷贝概念

由上述定义可知,所谓浅拷贝即是只拷贝对象第一层而不拷贝其子对象。

3.浅拷贝演示

对于列表的拷贝我们可以使用列表内置的copy方法,当然也可以使用copy模块的copy方法,都会讲到。废话不说了,开搞。

>>> ls1 = [1,2,3,4,5]
>>> ls2 = ls.copy()
>>> ls1
[1, 2, 3, 4, 5]
>>> ls2
[1, 2, 3, 4, 5]

列表中的copy方法是浅拷贝,我们定义了ls1变量并赋值了一个列表对象,接着又把对象拷贝给了ls2,可以用内置方法id()查看拷贝后类ls1、ls2的内存地址,当然结果大家也应该知道浅拷贝是能拷贝对象第一层的,而非只是引用,所以内存地址必然不同。

>>> id(ls1)
744702724096
>>> id(ls2)
744702724160

故而在改变其中一个的值时另一个的值也不会改变

>>> ls1.append(6)
>>> ls1
[1, 2, 3, 4, 5, 6]
>>> ls2
[1, 2, 3, 4, 5]

但若是为需要拷贝的内容加上子对象呢?已经讲过子对象无法被浅拷贝所拷贝,这里我们就为ls1重新赋值加上一个列表子对象,再将其拷贝。

>>> ls1 = [1,2,3,[4,5,6]]
>>> ls2 = ls1.copy()
>>>> ls1
[1, 2, 3, [4, 5, 6]]
>>> ls2
[1, 2, 3, [4, 5, 6]]
>>> id(ls1)
744702725824
>>> id(ls2)
744702726080

如上面代码所示,第一层对象的拷贝是成功了的,但子对象…

>>> id(ls1[3])
744702460544
>>> id(ls2[3])
744702460544
>>>

就只是简单引用了,既然是引用的是同一个内存数据,那么我改变其中一个,另一个自然也要改变。

>>> ls1
[1, 2, 3, [4, 5, 6]]
>>> ls2
[1, 2, 3, [4, 5, 6]]
>>> ls1[3].append(9)
>>> ls1
[1, 2, 3, [4, 5, 6, 9]]
>>> ls2
[1, 2, 3, [4, 5, 6, 9]]
>>>

为了方便拷贝,python中提供了对象拷贝模块,copy模块
用import copy命令引入该模块

import copy

在copy模块下亦有一个copy方法(copy.copy)与列表自带的copy方法功能相同,也是浅拷贝,就不多加赘述了,只是提一下,因为深拷贝要用到

>>> ls = [1,2,3,[1,2,3],4]
>>> ls2 = ls.copy()
>>> id(ls2[3]) //第二层
375434153856
>>> id(ls[3])  //第二层
375434153856
>>> ls[3][2]=22222   //操作子对象
>>> ls
[1, 2, 3, [1, 2, 22222], 4]
>>> ls2
[1, 2, 3, [1, 2, 22222], 4]
>>> ls1 = copy.copy(ls)
>>> ls1
[1, 2, 3, [1, 2, 22222], 4]
>>> ls
[1, 2, 3, [1, 2, 22222], 4]
>>> id(ls)
375433973184
>>> id(ls[3])
375434153856
>>> id(ls1[3])
375434153856

4.深拷贝概念

由上述定义可知,所谓深拷贝即是拷贝对象并拷贝对象下的子对象。

5.深拷贝演示

我们已经了解了深拷贝的概念,现在具体使用,为了方便使用,我们这里也使用copy模块进行拷贝,而深拷贝的底层逻辑,是使用的递归原理完成拷贝,如果对递归概念不太了解可以点击下面的链接。
python篇 递归使用

下面介绍copy模块中另一个“copy”方法,也就是深拷贝方法:
copy.deepcopy,下面我们定义一个含有子对象的ls变量,并用深拷贝给ls1变量

>>> ls
[1, 2, 3, [1, 2, 22222], 4]
>>> ls1 = copy.deepcopy(ls)
>>> ls1
[1, 2, 3, [1, 2, 22222], 4]

同样用全局函数id查看其子对象内存地址,可知其子对象内存地址值不同,已完成拷贝,而非简单引用。

>>> id(ls[3])
744702914816
>>> id(ls1[3])
744702725824

理所应该的改变其中一个的子对象,另一个不会发生改变。


>>> ls
[1, 2, 3, [1, 2, 22222], 4]
>>> ls[3].append("哈哈哈")
>>> ls
[1, 2, 3, [1, 2, 22222, '哈哈哈'], 4]
>>> ls1
[1, 2, 3, [1, 2, 22222], 4]

下面做个小总:

一般需要拷贝对象的时候,一般建议大家使用拷贝为浅拷贝,只拷贝一层,效率会高一点,占用内存会少一点,如果需要完全分离就使用深拷贝;
特殊情况:不可变类型(元组,字符串),无论浅拷贝还是深拷贝都永远只有一份(引用)

出道题感兴趣的可以下去尝试:

元组中的元素是可变的,浅拷贝和深拷贝会发生啥?

>>> t = (1,2,[3,4,5])
>>> tt = copy.copy(t)
>>> ttt = copy.deepcopy(t)
>>> ttt = copy.deepcopy(t)
>>> t is tt
True
>>> t is ttt
False
>>>

答曰:会全数复制一份其不可变对象

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:40:40  更:2021-12-11 15:40:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 4:24:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码