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进行数据科学工作的简单入门教程
Apr 01 Python
用Python的Django框架完成视频处理任务的教程
Apr 02 Python
Python urllib、urllib2、httplib抓取网页代码实例
May 09 Python
python删除过期文件的方法
May 29 Python
TensorFlow损失函数专题详解
Apr 26 Python
PyCharm代码整体缩进,反向缩进的方法
Jun 25 Python
Python+PyQT5的子线程更新UI界面的实例
Jun 14 Python
python3将变量写入SQL语句的实现方式
Mar 02 Python
Python OpenCV实现测量图片物体宽度
May 27 Python
tensorflow 2.1.0 安装与实战教程(CASIA FACE v5)
Jun 30 Python
Python自动化之批量处理工作簿和工作表
Jun 03 Python
python 远程执行命令的详细代码
Feb 15 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的宝库目录--PEAR
2006/10/09 PHP
安装APACHE
2007/01/15 PHP
二进制交叉权限微型php类分享
2014/02/07 PHP
php实现将wav文件转换成图像文件并在页面中显示的方法
2015/04/21 PHP
Laravel与CI框架中截取字符串函数
2016/05/08 PHP
Smarty环境配置与使用入门教程
2016/05/11 PHP
php抽象类和接口知识点整理总结
2019/08/02 PHP
php+js实现的拖动滑块验证码验证表单操作示例【附源码下载】
2020/05/27 PHP
json 实例详细说明教程
2009/10/31 Javascript
JavaScript游戏之优化篇
2010/11/08 Javascript
jquery 图片缩放拖动的简单实例
2014/01/08 Javascript
js离开或刷新页面检测(且兼容FF,IE,Chrome)
2014/03/05 Javascript
javascript白色简洁计算器
2015/05/04 Javascript
原生js模拟淘宝购物车项目实战
2015/11/18 Javascript
信息页文内画中画广告js实现代码(文中加载广告方式)
2016/01/03 Javascript
JavaScript数组去重由慢到快由繁到简(优化篇)
2016/08/26 Javascript
AngularJS动态绑定HTML的方法分析
2016/11/07 Javascript
JavaScript实现多栏目切换效果
2016/12/12 Javascript
Vue组件通信实践记录(推荐)
2017/08/15 Javascript
JS实现常见的查找、排序、去重算法示例
2018/05/21 Javascript
ES6的解构赋值实例详解
2019/05/06 Javascript
微信小程序与公众号实现数据互通的方法
2019/07/25 Javascript
微信小程序修改数组长度的问题的解决
2019/12/17 Javascript
vue实现选中效果
2020/10/07 Javascript
在Django的模型和公用函数中使用惰性翻译对象
2015/07/27 Python
实例讲解Python编程中@property装饰器的用法
2016/06/20 Python
Python使用requests xpath 并开启多线程爬取西刺代理ip实例
2020/03/06 Python
DjangoWeb使用Datatable进行后端分页的实现
2020/05/18 Python
CSS3用@font-face实现自定义英文字体
2013/09/23 HTML / CSS
将HTML5 Canvas的内容保存为图片借助toDataURL实现
2013/05/20 HTML / CSS
处理textarea中的换行和空格
2019/12/12 HTML / CSS
经验丰富大学生村干部自我鉴定
2014/01/22 职场文书
人事部专员岗位职责
2014/03/04 职场文书
2014年安全生产目标责任书
2014/07/23 职场文书
三峡人家导游词
2015/01/31 职场文书
第一书记观后感
2015/06/08 职场文书