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语言的优雅之处
Jul 04 Python
Python的装饰器使用详解
Jun 26 Python
python更改已存在excel文件的方法
May 03 Python
Python Logging 日志记录入门学习
Jun 02 Python
Python 爬取携程所有机票的实例代码
Jun 11 Python
Python将一个CSV文件里的数据追加到另一个CSV文件的方法
Jul 04 Python
Python Django框架防御CSRF攻击的方法分析
Oct 18 Python
python list多级排序知识点总结
Oct 23 Python
postman和python mock测试过程图解
Feb 22 Python
浅析Python __name__ 是什么
Jul 07 Python
如何教少儿学习Python编程
Jul 10 Python
python制作微博图片爬取工具
Jan 16 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
全国FM电台频率大全 - 30 宁夏回族自治区
2020/03/11 无线电
shopex主机报错误请求解决方案(No such file or directory)
2011/12/27 PHP
屏蔽机器人从你的网站搜取email地址的php代码
2012/11/14 PHP
php的curl封装类用法实例
2014/11/07 PHP
jQuery+PHP实现的掷色子抽奖游戏实例
2015/01/04 PHP
PHP实现简单日历类编写
2020/08/28 PHP
jquery中的$(document).ready()与window.onload的区别
2009/11/18 Javascript
IE6/7 and IE8/9/10(IE7模式)依次隐藏具有absolute或relative的父元素和子元素后再显示父元素
2011/07/31 Javascript
原生js实现复制对象、扩展对象 类似jquery中的extend()方法
2014/08/30 Javascript
详解AngularJS中的表格使用
2015/06/16 Javascript
jQuery实现可高亮显示的二级CSS菜单效果
2015/09/01 Javascript
使用bootstrap实现多窗口和拖动效果
2016/09/22 Javascript
node.js发送邮件email的方法详解
2017/01/06 Javascript
VueJS如何引入css或者less文件的一些坑
2017/04/25 Javascript
React服务端渲染(总结)
2017/07/01 Javascript
Vue 项目中遇到的跨域问题及解决方法(后台php)
2018/03/28 Javascript
详解基于iview-ui的导航栏路径(面包屑)配置
2019/02/22 Javascript
一文秒懂nodejs中的异步编程
2021/01/28 NodeJs
[01:03:37]Secret vs VGJ.S Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
python实现图片文件批量重命名
2020/03/23 Python
解决pyecharts在jupyter notebook中使用报错问题
2020/04/23 Python
python实现拉普拉斯特征图降维示例
2019/11/25 Python
numpy ndarray 取出满足特定条件的某些行实例
2019/12/05 Python
Python接口测试数据库封装实现原理
2020/05/09 Python
详解用selenium来下载小姐姐图片并保存
2021/01/26 Python
Python对excel的基本操作方法
2021/02/18 Python
企业厂长岗位职责
2013/12/17 职场文书
五年级英语教学反思
2014/01/31 职场文书
2014法制宣传日活动总结
2014/07/09 职场文书
毕业论文致谢词
2015/05/14 职场文书
CAD实训总结范文
2015/08/03 职场文书
商务宴会祝酒词
2015/08/11 职场文书
关于车尾的标语大全
2015/08/11 职场文书
2016年教师学习廉政准则心得体会
2016/01/20 职场文书
python图像处理基本操作总结(PIL库、Matplotlib及Numpy)
2021/06/08 Python
Python绘画好看的星空图
2022/03/17 Python