Python对象的深拷贝和浅拷贝详解


Posted in Python onAugust 25, 2014

本文内容是在《Python核心编程2》上看到的,感觉很有用便写出来,给大家参考参考!

浅拷贝

首先我们使用两种方式来拷贝对象,一种是切片,另外一种是工厂方法。然后使用id函数来看看它们的标示符

# encoding=UTF-8

 

obj = ['name',['age',18]]

a=obj[:]

b=list(obj)

for x in obj,a,b:

    print id(x)

 

35217032

35227912

29943304

 
他们的id都不同,按照正常的判断,三个不同id的对象应该都是独立的。那么我们先给他们改改名看看
# encoding=UTF-8

 

obj = ['name',['age',18]]

a=obj[:]

b=list(obj)

for x in obj,a,b:

    print id(x)

     

a[0] = 'lisi'

b[0] = 'zhangsan'

 

print a

print b

 

35217032

35227912

33547784

['lisi', ['age', 18]]

['zhangsan', ['age', 18]]

对象a与b分别赋予了不同的名字,下来我们来看看给a对象改一个年龄
# encoding=UTF-8

 

obj = ['name',['age',18]]

a=obj[:]

b=list(obj)

for x in obj,a,b:

    print id(x)

     

a[0] = 'lisi'

b[0] = 'zhangsan'

 

print a

print b

 

a[1][1] = 25

 

print a

print b

 

35217032

35227912

29943304

['lisi', ['age', 18]]

['zhangsan', ['age', 18]]

['lisi', ['age', 25]]

['zhangsan', ['age', 25]]

细心的朋友应该看出来了,改变a[0]元素与b[0]元素都互不影响,为何改变a[1][1]的元素会影响b[1][1]的元素呢?
要解开这个问题,只有先了解深拷贝与浅拷贝。以上实例中,我们创建的a与b都是从obj对象的浅拷贝,obj中第一个元素是字符串属于不可变类型,第二个元素是列表属于可变类型。因此我们进行拷贝对象时,字符串被显示拷贝重新创建了一个字符串,而列表只是复制引用,所以改变列表的元素会影响所有引用对象。从下列的id值中,你就能看明白了
# encoding=UTF-8

 

obj = ['name',['age',18]]

a=obj[:]

b=list(obj)

 

for x in obj,a,b:

    print id(x[0]),id(x[1])

print

 

a[0] = 'lisi'

b[0] = 'zhangsan'

 

for x in obj,a,b:

    print id(x[0]),id(x[1])

print

 

a[1][1] = 25

b[1][1] = 30

 

for x in obj,a,b:

    print id(x[0]),id(x[1])

print

 

32564088 34496008

32564088 34496008

32564088 34496008

 

32564088 34496008

34574704 34496008

33970672 34496008

 

32564088 34496008

34574704 34496008

33970672 34496008

复制对象的时候,我们可以看到所有元素的id都一直,我们分别改变了a与b对象的第一个字符串元素,因为字符串是不可变对象,所以改变后等于新创建,于是a与b的第一个字符串元素id不一致。而a与b的第二个元素都是列表可变对象,所以无论修改任何一个id值都表示一个指针,始终影响其它引用对象的值。
因此也就为什么修改a对象的年龄会影响b对象的年龄值,或者修改b对象的年龄值也会影响a对象的年龄值,包括obj对象在内。

深拷贝

以上都是浅拷贝,那么我们希望拷贝的对象是独立的,修改时不要影响其它值,这种我们称为深拷贝。实现深拷贝我们需要引用一个copy模块,copy模块有两个函数可用,一个是copy浅拷贝;另一个是deepcopy深拷贝。

# encoding=UTF-8

import copy

obj = ['name',['age',18]]

a=copy.deepcopy(obj)

b=copy.deepcopy(obj)

 

for x in a,b:

    print id(x[0]),id(x[1])

print

 

a[1][1] = 25

b[1][1] = 30

 

print a

print b

 

33612664 35477256

33612664 35477640

 

['name', ['age', 25]]

['name', ['age', 30]]

使用深拷贝后,列表元素的id不一致,表示独立对象,修改任何一个列表元素的值都不会影响其它对象。

以下是几点拷贝操作的注意事项:
第一、非容器类型(比如数字、字符串和其它“院子”类型的对象,像代码、类型和range对象等)没有被拷贝一说,浅拷贝是用完全切片操作来完成。

第二、如果元祖变量只包含原子类型对象,对它的深拷贝将不会进行。
我们把上面的例子改成元祖,然后使用深拷贝试试

# encoding=UTF-8

import copy

obj = ['name',('age',18)]

a=copy.deepcopy(obj)

b=copy.deepcopy(obj)

 

for x in a,b:

    print id(x),id(x[1])

print

 

34703752 34693000

34756616 34693000
Python 相关文章推荐
使用Python编写爬虫的基本模块及框架使用指南
Jan 20 Python
Python设计足球联赛赛程表程序的思路与简单实现示例
Jun 28 Python
Python内置函数OCT详解
Nov 09 Python
python执行使用shell命令方法分享
Nov 08 Python
python实现拓扑排序的基本教程
Mar 11 Python
python MySQLdb使用教程详解
Mar 20 Python
python基础教程项目二之画幅好画
Apr 02 Python
Python实现读取SQLServer数据并插入到MongoDB数据库的方法示例
Jun 09 Python
PyQt 图解Qt Designer工具的使用方法
Aug 06 Python
tensorflow安装成功import tensorflow 出现问题
Apr 16 Python
python简单实现9宫格图片实例
Sep 03 Python
Python tkinter之Bind(绑定事件)的使用示例
Feb 05 Python
Python3实现连接SQLite数据库的方法
Aug 23 #Python
Python3实现生成随机密码的方法
Aug 23 #Python
Python实现Linux下守护进程的编写方法
Aug 22 #Python
Python实现远程调用MetaSploit的方法
Aug 22 #Python
Python解释执行原理分析
Aug 22 #Python
Python实现的石头剪子布代码分享
Aug 22 #Python
Python使用MD5加密字符串示例
Aug 22 #Python
You might like
使用 php4 加速 web 传输
2006/10/09 PHP
window+nginx+php环境配置 附配置搭配说明
2010/12/29 PHP
curl不使用文件存取cookie php使用curl获取cookie示例
2014/01/26 PHP
php 数组随机取值的简单实例
2016/05/23 PHP
PHP之十六个魔术方法详细介绍
2016/11/01 PHP
PHP mongodb操作类定义与用法示例【适合mongodb2.x和mongodb3.x】
2018/06/16 PHP
jQuery实现的一个自定义Placeholder属性插件
2014/08/11 Javascript
JS基于Mootools实现的个性菜单效果代码
2015/10/21 Javascript
JavaScript中undefined和null的区别
2017/05/03 Javascript
深入浅析var,let,const的异同点
2018/08/07 Javascript
详解vue-router数据加载与缓存使用总结
2018/10/29 Javascript
vue el-tree 默认展开第一个节点的实现代码
2020/05/15 Javascript
vue npm install 安装某个指定的版本操作
2020/08/11 Javascript
微信小程序实现天气预报功能(附源码)
2020/12/10 Javascript
[02:51]DOTA2 2015国际邀请赛中国区预选赛第一日战报
2015/05/27 DOTA
[54:06]OG vs TNC 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[59:15]EG vs LGD 2018国际邀请赛淘汰赛BO3 第一场 8.26
2018/08/29 DOTA
浅谈Python 对象内存占用
2016/07/15 Python
详谈Python基础之内置函数和递归
2017/06/21 Python
Python3实现简单可学习的手写体识别(实例讲解)
2017/10/21 Python
对python多线程SSH登录并发脚本详解
2019/02/14 Python
使用turtle绘制五角星、分形树
2019/10/06 Python
使用python的turtle绘画滑稽脸实例
2019/11/21 Python
keras小技巧——获取某一个网络层的输出方式
2020/05/23 Python
如何一键升级Python所有包
2020/11/05 Python
前端隐藏出边界内容的实现方法
2016/04/14 HTML / CSS
美国新兴城市生活方式零售商:VILLA
2017/12/06 全球购物
英国知名化妆品网站:Revolution Beauty(原TAM Beauty)
2018/02/28 全球购物
Yahoo-PHP面试题2
2014/12/06 面试题
财务管理专业应届毕业生求职信
2013/09/22 职场文书
医学生自荐信范文
2013/12/03 职场文书
经典促销广告词大全
2014/03/19 职场文书
2014年科研工作总结
2014/12/03 职场文书
建议书的格式及范文
2015/09/14 职场文书
小学数学继续教育研修日志
2015/11/13 职场文书
接收函
2019/04/22 职场文书