Python深拷贝与浅拷贝用法实例分析


Posted in Python onMay 05, 2019

本文实例讲述了Python深拷贝与浅拷贝用法。分享给大家供大家参考,具体如下:

1、对象的赋值

对象的赋值实际上是对象之间的引用:当创建一个对象,然后将这个对象赋值给另外一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用。

当对对象做赋值或者是参数传递或者作为返回值的时候,总是传递原始对象的引用,而不是一个副本。如下所示:

在python中将一个变量赋值给另一个变量,传递的是引用.无论是a的内层变化还是外层变化,b都会发生同样的变化.因为b和a指向了同一个引用.类似于c语言中的同一片内存地址.

#coding=utf-8
a = [1,2,3,['a','b','c']]
b = a
print('*'*50)
print('--- b = a ---')
print('a = %s'%a)
print('b = %s'%b)
a.append(4)
print('--- 外层a增加了元素4 ---')
print('a = %s'%a)
print('b = %s'%b)
print('--- 内层增加了元素"d" ---')
a[3].append('d')
print('a = %s'%a)
print('b = %s'%b)

运行结果:

**************************************************
--- b = a ---
a = [1, 2, 3, ['a', 'b', 'c']]
b = [1, 2, 3, ['a', 'b', 'c']]
--- 外层a增加了元素4 ---
a = [1, 2, 3, ['a', 'b', 'c'], 4]
b = [1, 2, 3, ['a', 'b', 'c'], 4]
--- 内层增加了元素'd' ---
a = [1, 2, 3, ['a', 'b', 'c', 'd'], 4]
b = [1, 2, 3, ['a', 'b', 'c', 'd'], 4]

2、对象的复制

当你想修改一个对象,而且让原始的对象不受影响的时候,那么就需要使用到对象的复制,对象的复制可以通过三种方法实现:

a、 使用切片操作进行拷贝 - -slice operation

(注:切片技术应用于所有的序列,包括:列表、字符串、元祖 ,但切片不能应用于字典。对字典只能使用D.copy()方法或D.deepcopy()方法.)

b、 使用工厂函数进行拷贝,list / dir / set - -factoryfunction

c、 copy.copy()?use copymodule

在复制的时候,使用的是浅拷贝,复制了对象,但是对象中的元素,依然使用引用。

如下所示:

a = [1,2,3,['a','b','c']]

#coding=utf-8
import copy
#1.切片操作
print('--- 切片操作 ---')
b = a[:]
print('a = %s\tid(a) = %s'%(a,id(a)))
print('b = %s\tid(b) = %s'%(b,id(b)))
#2.使用工厂函数
print('--- 使用工厂函数 ---')
c = list(a)
print('a = %s\tid(a) = %s'%(a,id(a)))
print('c = %s\tid(c) = %s'%(c,id(c)))
#3.copy.copy()
print('--- copy.copy() ---')
d = copy.copy(a)
print('a = %s\tid(a) = %s'%(a,id(a)))
print('d = %s\tid(d) = %s'%(d,id(d)))

运行结果:

--- 切片操作 ---
a = [1, 2, 3, ['a', 'b', 'c']]  id(a) = 140676047022088
b = [1, 2, 3, ['a', 'b', 'c']]  id(b) = 140676047021320
--- 使用工厂函数 ---
a = [1, 2, 3, ['a', 'b', 'c']]  id(a) = 140676047022088
c = [1, 2, 3, ['a', 'b', 'c']]  id(c) = 140676047101640
--- copy.copy() ---
a = [1, 2, 3, ['a', 'b', 'c']]  id(a) = 140436217635720
d = [1, 2, 3, ['a', 'b', 'c']]  id(d) = 140436217656904

在使用浅拷贝的时候,发现引用的id都是相同的,但是字符串的id却发生了变化,是因为在python中,字符串是不可变的,从而在每次进行修改的时候,都是新建一个对象,从而引用发生了变化.

在不可变类型中,数字和字符串都是不可变类型,从而在每次修改的时候,都是新创建一个对象。

3、模块

核心模块:copy

浅拷贝和深拷贝的操作都可以在copy模块中找到,其实copy模块中只有两个函数可用,copy()进行浅拷贝操作,而deepcopy()进行深拷贝操作.

如下所示:

#coding=utf-8
import copy
a = [1,2,3,['a','b','c']]
#浅拷贝拷贝的是外层即顶级对象,对于内层只拷贝引用
#所以在a的外层增加了元素,而c并没有变化.而在a的内层增加元素后,c发生了同样的变化.(回顾b=a)
print('*'*50)
print('--- c = copy.copy(a)---')
c = copy.copy(a)
print('a = %s'%a)
print('c = %s'%c)
a.append(4)
print('---外层a增加了元素4---')
print('a = %s'%a)
print('c = %s'%c)
print('---内层增加了元素"d"---')
a[3].append('d')
print('a = %s'%a)
print('c = %s'%c)
#深拷贝会递归的拷贝所有内容,将所有的内容都独自拷贝了一份.
#故而,无论a的外层还是内层发生变化,都不会影响到d.
print('*'*50)
print('--- d = copy.deepcopy(a) ---')
d = copy.deepcopy(a)
print('a = %s'%a)
print('d = %s'%d)
a.append(5)
print('---外层a增加了元素5---')
print('a = %s'%a)
print('d = %s'%d)
print('---内层增加了元素"e"---')
a[3].append('e')
print('a = %s'%a)
print('d = %s'%d)

运行如下:

**************************************************
--- c = copy.copy(a)---
a = [1, 2, 3, ['a', 'b', 'c']]
c = [1, 2, 3, ['a', 'b', 'c']]
---外层a增加了元素4---
a = [1, 2, 3, ['a', 'b', 'c'], 4]
c = [1, 2, 3, ['a', 'b', 'c']]
---内层增加了元素"d"---
a = [1, 2, 3, ['a', 'b', 'c', 'd'], 4]
c = [1, 2, 3, ['a', 'b', 'c', 'd']]
**************************************************
--- d = copy.deepcopy(a) ---
a = [1, 2, 3, ['a', 'b', 'c', 'd'], 4]
d = [1, 2, 3, ['a', 'b', 'c', 'd'], 4]
---外层a增加了元素5---
a = [1, 2, 3, ['a', 'b', 'c', 'd'], 4, 5]
d = [1, 2, 3, ['a', 'b', 'c', 'd'], 4]
---内层增加了元素"e"---
a = [1, 2, 3, ['a', 'b', 'c', 'd', 'e'], 4, 5]
d = [1, 2, 3, ['a', 'b', 'c', 'd'], 4]

4、拷贝的警告

第一:非容器类型(比如数字,字符串和其他原子类型的对象,例如代码,类型和xrange对象等)没有拷贝一说,浅拷贝是完全用切片操作来完成的。

第二:如果元组变量只包含原子类型对象,那么深拷贝将不会进行。

#coding=utf-8
import copy
a = (1,2,3)
print('*'*50)
print('--- c = copy.copy(a)---')
c = copy.copy(a)
print(a,id(a))
print(c,id(c))
print('*'*50)
print('--- d = copy.deepcopy(a) ---')
d = copy.deepcopy(a)
print(a,id(a))
print(d,id(c))

运行如下:

**************************************************
--- c = copy.copy(a)---
(1, 2, 3) 140394676674992
(1, 2, 3) 140394676674992
**************************************************
--- d = copy.deepcopy(a) ---
(1, 2, 3) 140394676674992
(1, 2, 3) 140394676674992

可见:

对于可变类型来说,深拷贝和浅拷贝是不同的.

而对于不可变类型来说,深拷贝和浅拷贝的结果相同!

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
用python实现的去除win下文本文件头部BOM的代码
Feb 10 Python
使用Python的Tornado框架实现一个Web端图书展示页面
Jul 11 Python
关于Tensorflow中的tf.train.batch函数的使用
Apr 24 Python
浅谈Tensorflow模型的保存与恢复加载
Apr 26 Python
对Python3中的print函数以及与python2的对比分析
May 02 Python
python-django中的APPEND_SLASH实现方法
Jun 21 Python
Python实现 PS 图像调整中的亮度调整
Jun 28 Python
Python 绘制酷炫的三维图步骤详解
Jul 12 Python
python判断链表是否有环的实例代码
Jan 31 Python
Python使用Paramiko控制liunx第三方库
May 20 Python
Python实现初始化不同的变量类型为空值
Jun 02 Python
详解利用python识别图片中的条码(pyzbar)及条码图片矫正和增强
Nov 17 Python
Python3中函数参数传递方式实例详解
May 05 #Python
python制作填词游戏步骤详解
May 05 #Python
python开发游戏的前期准备
May 05 #Python
Python实现多态、协议和鸭子类型的代码详解
May 05 #Python
用uWSGI和Nginx部署Flask项目的方法示例
May 05 #Python
基于python实现高速视频传输程序
May 05 #Python
Python远程视频监控程序的实例代码
May 05 #Python
You might like
PHP代码优化的53个细节
2014/03/03 PHP
PHP FATAL ERROR: CALL TO UNDEFINED FUNCTION BCMUL()解决办法
2014/05/04 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(八)
2014/06/23 PHP
利用PHP将图片转换成base64编码的实现方法
2016/09/13 PHP
关于PHP内置的字符串处理函数详解
2017/02/04 PHP
拖动一个HTML元素
2006/12/22 Javascript
javascript flash下fromCharCode和charCodeAt方法使用说明
2008/01/12 Javascript
AJAX使用了UpdatePanel后无法使用alert弹出脚本
2010/04/02 Javascript
突发奇想的一个jquery插件
2010/11/19 Javascript
用JQuery在网页中实现分隔条功能的代码
2012/08/09 Javascript
js读写(删除)Cookie实例详解
2013/04/17 Javascript
用js来刷新当前页面保留参数的具体实现
2013/12/23 Javascript
javascript对象的使用和属性操作示例详解
2014/03/02 Javascript
javascript实现自动填写表单实例简析
2015/12/02 Javascript
AngularJS 所有版本下载地址
2016/09/14 Javascript
jQuery使用Layer弹出层插件闪退问题
2016/12/22 Javascript
JS操作xml对象转换为Json对象示例
2017/03/25 Javascript
Vuejs 2.0 子组件访问/调用父组件的方法(示例代码)
2018/02/08 Javascript
p5.js入门教程之鼠标交互的示例
2018/03/16 Javascript
r.js来合并压缩css文件的示例
2018/04/26 Javascript
vue项目使用.env文件配置全局环境变量的方法
2019/10/24 Javascript
详解python中executemany和序列的使用方法
2017/08/12 Python
Python中is和==的区别详解
2018/11/15 Python
jenkins配置python脚本定时任务过程图解
2019/10/29 Python
pytorch如何冻结某层参数的实现
2020/01/10 Python
Django User 模块之 AbstractUser 扩展详解
2020/03/11 Python
python 基于selectors库实现文件上传与下载
2020/12/31 Python
英国二手iPhone、音乐、电影和游戏商店:musicMagpie
2018/10/26 全球购物
社区助残日活动总结
2014/08/29 职场文书
领导干部作风建设工作总结
2014/10/23 职场文书
2015年企业新年寄语
2014/12/08 职场文书
2015年物业管理工作总结
2015/04/23 职场文书
运动会200米广播稿
2015/08/19 职场文书
大学生学习十八届五中全会精神心得体会
2016/01/05 职场文书
java项目构建Gradle的使用教程
2022/03/24 Java/Android
Oracle删除归档日志及添加定时任务
2022/06/28 Oracle