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实现过滤单个Android程序日志脚本分享
Jan 16 Python
Django实现图片文字同时提交的方法
May 26 Python
Python实现批量将word转html并将html内容发布至网站的方法
Jul 14 Python
python 编程之twisted详解及简单实例
Jan 28 Python
插入排序_Python与PHP的实现版(推荐)
May 11 Python
Python 3.6 读取并操作文件内容的实例
Apr 23 Python
用Python写一个模拟qq聊天小程序的代码实例
Mar 06 Python
使用matplotlib中scatter方法画散点图
Mar 19 Python
使用python将最新的测试报告以附件的形式发到指定邮箱
Sep 20 Python
pytorch中的自定义反向传播,求导实例
Jan 06 Python
python将图片转base64,实现前端显示
Jan 09 Python
python GUI库图形界面开发之PyQt5动态加载QSS样式文件
Feb 25 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
discuz论坛更换域名,详细文件修改步骤
2020/12/09 PHP
初学Javascript的一些总结
2008/11/03 Javascript
多浏览器兼容性比较好的复制到剪贴板的js代码
2011/10/09 Javascript
js判断上传文件的类型和大小示例代码
2013/10/18 Javascript
JavaScript列表框listbox全选和反选的实现方法
2015/03/18 Javascript
jquery序列化方法实例分析
2015/06/10 Javascript
JS文字球状放大效果代码分享
2015/08/19 Javascript
Javascript实现单例模式
2016/01/24 Javascript
Ionic如何实现下拉刷新与上拉加载功能
2016/06/03 Javascript
深入理解React中es6创建组件this的方法
2016/08/29 Javascript
JS倒计时实例_天时分秒
2017/08/22 Javascript
AngularJS自定义表单验证功能实例详解
2018/08/24 Javascript
使用Node.js实现一个多人游戏服务器引擎
2019/03/13 Javascript
vue 地区选择器v-distpicker的常用功能
2019/07/23 Javascript
vue中提示$index is not defined错误的解决方式
2020/09/02 Javascript
[02:17]2016国际邀请赛中国区预选赛VG战队领队采访
2016/06/26 DOTA
[40:17]2018DOTA2亚洲邀请赛 4.5 淘汰赛 LGD vs Liquid 第一场
2018/04/06 DOTA
Python3基础之函数用法
2014/08/13 Python
详解如何为eclipse安装合适版本的python插件pydev
2018/11/04 Python
python中Lambda表达式详解
2019/11/20 Python
python不相等的两个字符串的 if 条件判断为True详解
2020/03/12 Python
pytorch判断是否cuda 判断变量类型方式
2020/06/23 Python
django 获取字段最大值,最新的记录操作
2020/08/09 Python
瑞贝卡·泰勒官方网站:Rebecca Taylor
2016/09/24 全球购物
英国川宁茶官方网站:Twinings茶
2019/05/21 全球购物
索尼巴西商店:Sony巴西
2019/06/21 全球购物
优秀中专生推荐信
2013/11/17 职场文书
应届毕业生专业个人求职自荐信格式
2013/11/20 职场文书
婚礼新郎父母答谢词
2014/01/16 职场文书
四风自我剖析材料思想汇报
2014/10/01 职场文书
公安交警中队队长个人对照检查材料思想汇报
2014/10/05 职场文书
新郎婚礼答谢词
2015/01/04 职场文书
软件项目经理岗位职责
2015/04/01 职场文书
2015年小学二年级班主任工作总结
2015/05/21 职场文书
在职证明书模板
2015/06/15 职场文书
公司出差管理制度范本
2015/08/05 职场文书