学委前面展示dict的概念和常用操作,谈到了一个shadow copy产生的新dict对象受到原dict对象影响。
这篇我们继续看看深拷贝,
深拷贝是什么?
我们拿字典的复制可以通过copy函数来实现,但是它是浅拷贝,也就是拷贝了但不完全拷贝
简单粗暴来说浅拷贝就是拷贝key,但是新字典的值还是沿用旧字典的值的引用(内存地址一样)。
与浅拷贝对比,深拷贝就是除了拷贝key,新字典的值不会沿用旧字典值的引用,而是创建类似的数据,引用分开!
也就是内存分配两个空间内串联起来的数据块,是可以做到毫无关联!
我们看看字典的深浅拷贝对比代码示例:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2021/11/6 11:25 下午 # @Author : LeiXueWei # @CSDN/Juejin/Wechat: 雷学委 # @XueWeiTag: CodingDemo # @File : thecopy.py # @Project : hello import copy # 引入了copy模块,3.8自带的模块 info_dict = dict() info_dict['name'] = 'LEI_XUE_WEI' # 或者改为 'levin' info_dict['blogs'] = '95' # 目前发表了93个博客文字。 info_dict['gongzhong_hao'] = '【雷学委】' # 欢迎过来关注支持 info_dict['meta-data'] = dict() print('info_dict:', info_dict) print("*" * 16) # 浅拷贝//Shadow Copy: 全拷贝但不完全拷贝 shadow_copied_dict = info_dict.copy() # 也可以使用: copy.copy(info_dict) print("shadow_copied_dict :", shadow_copied_dict) deepcopied_dict = copy.deepcopy(info_dict) print("deepcopied_dict :", deepcopied_dict) # 我们修改原始的dict info_dict['meta-data']['date'] = '06 Nov 2021' print('info_dict:', info_dict) print('shadow_copied_dict:', shadow_copied_dict) # 这里输出看到变化也传递给了 shadow_copied_dict print('deepcopied_dict:', deepcopied_dict) # 这里输出看到变化也传递给了 deepcopied_dict
效果如下:
从这里看,我们发现两个拷贝的字典,浅拷贝因为被拷贝的字典产生变更而更新了。
而深拷贝产生的deepcopied_dict对象则纹丝不动!
这里还得说一下copy模块。
稍微说说copy.deepcopy函数的原理
考虑到基础系列专栏,这一段会比较难以理解,我会再以后的文章更加细致讲。
这里只针对dict对象的拷贝做带过:
deepcopy内部通过_deepcopy_dispatch对象查找字典(dict)的拷贝器
拷贝器定义的拷贝方法遍历原字典对象
依次对key 和 value 进行深度拷贝
就这么简单,如果key和value还不是最简单的类型(比如int/float/str等),继续查找拷贝器,遍历进行拷贝,直到基础类型直接返回,然后回溯。
小白可以跳过这一段继续学习,先把基础熟练了。
总结
深拷贝和浅拷贝涉及的技术很多。
本篇只是介绍了怎么进行深拷贝(借用copy模块),也侧重于展示和使用介绍
如果不用怎么实现呢?
当然copy模块也给了我们一个参考答案,但这个背后涉及了pickle序列化反序列化还有内存管理等,不难但篇幅更长以后再说。