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学习笔记之常用函数及说明
May 23 Python
Python处理命令行参数模块optpars用法实例分析
May 31 Python
Windows 64位下python3安装nltk模块
Sep 19 Python
python 构造三维全零数组的方法
Nov 12 Python
Django框架模板文件使用及模板文件加载顺序分析
May 23 Python
Flask框架学习笔记之表单基础介绍与表单提交方式
Aug 12 Python
详解python中index()、find()方法
Aug 29 Python
Django异步任务线程池实现原理
Dec 17 Python
Python实现隐马尔可夫模型的前向后向算法的示例代码
Dec 31 Python
python3 Scrapy爬虫框架ip代理配置的方法
Jan 17 Python
python 使用三引号时容易犯的小错误
Oct 21 Python
python爬虫用scrapy获取影片的实例分析
Nov 23 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和Mysqlweb应用开发核心技术-第1部分 Php基础-2 php语言介绍
2011/07/03 PHP
解析如何屏蔽php中的phpinfo()函数
2013/06/06 PHP
php使用ZipArchive提示Fatal error: Class ZipArchive not found in的解决方法
2014/11/04 PHP
搭建基于Docker的PHP开发环境的详细教程
2015/07/01 PHP
yii2中的rules 自定义验证规则详解
2016/04/19 PHP
thinkPHP自动验证、自动添加及表单错误问题分析
2016/10/17 PHP
些很实用且必用的小脚本代码
2006/06/26 Javascript
javascript parseInt 大改造
2009/09/27 Javascript
jquery 跨域访问问题解决方法(笔记)
2011/06/08 Javascript
Javascript中查找不以XX字符结尾的单词示例代码
2013/10/15 Javascript
js实现简单登录功能的实例代码
2013/11/09 Javascript
js获取客户端外网ip的简单实例
2013/11/21 Javascript
js验证整数加保留小数点的简单实例
2013/12/02 Javascript
js 动态为textbox添加下拉框数据源的方法
2014/04/24 Javascript
javascript中setTimeout的问题解决方法
2014/05/08 Javascript
jQuery移除tr无效的解决方法(tr是动态添加)
2014/09/22 Javascript
JavaScript中style.left与offsetLeft的使用及区别详解
2016/06/08 Javascript
使用vuex存储用户信息到localStorage的实例
2019/11/11 Javascript
vue 动态组件用法示例小结
2020/03/06 Javascript
原生JavaScript写出Tabs标签页的实例代码
2020/07/20 Javascript
[01:25]2014DOTA2国际邀请赛 zhou分析LGD比赛情况
2014/07/14 DOTA
[01:06]DOTA2小知识课堂 Ep.02 吹风竟可解梦境缠绕
2019/12/05 DOTA
Python set集合类型操作总结
2014/11/07 Python
python实现可将字符转换成大写的tcp服务器实例
2015/04/29 Python
python 哈希表实现简单python字典代码实例
2019/09/27 Python
使用Python实现正态分布、正态分布采样
2019/11/20 Python
python GUI库图形界面开发之PyQt5窗口布局控件QStackedWidget详细使用方法
2020/02/27 Python
Python类的绑定方法和非绑定方法实例解析
2020/03/04 Python
浅谈keras使用预训练模型vgg16分类,损失和准确度不变
2020/07/02 Python
新加坡最受追捧的体验平台:Hapz
2018/01/01 全球购物
四年大学生活的个人自我评价
2013/12/11 职场文书
高一物理教学反思
2014/01/24 职场文书
物理力学求职信
2014/02/18 职场文书
亲子拓展活动方案
2014/02/20 职场文书
对外汉语专业大学生职业生涯规划范文
2014/09/13 职场文书
教师党员整改措施
2014/10/24 职场文书