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的词法分析与语法分析
May 18 Python
python实现逻辑回归的方法示例
May 02 Python
分享给Python新手们的几道简单练习题
Sep 21 Python
Python简单实现控制电脑的方法
Jan 22 Python
python简单商城购物车实例代码
Mar 15 Python
python 格式化输出百分号的方法
Jan 20 Python
Pandas DataFrame数据的更改、插入新增的列和行的方法
Jun 25 Python
python变量命名的7条建议
Jul 04 Python
100行Python代码实现每天不同时间段定时给女友发消息
Sep 27 Python
python中常见错误及解决方法
Jun 21 Python
用opencv给图片换背景色的示例代码
Jul 08 Python
python字典进行运算原理及实例分享
Aug 02 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
索尼ICF-SW100收音机评测
2021/03/02 无线电
10款实用的PHP开源工具
2015/10/23 PHP
POST一个JSON格式的数据给Restful服务实例详解
2017/04/07 PHP
对于Laravel 5.5核心架构的深入理解
2018/02/22 PHP
设定php简写功能的方法
2019/11/28 PHP
JS打开新窗口的2种方式
2013/04/18 Javascript
javascript break指定标签打破多层循环示例
2014/01/20 Javascript
JavaScript实现获得所有兄弟节点的方法
2015/07/23 Javascript
js验证框架之RealyEasy验证详解
2016/06/08 Javascript
jQuery选择器之表单元素选择器详解
2017/09/19 jQuery
实例讲解javascript实现异步图片上传方法
2017/12/05 Javascript
vue中的数据绑定原理的实现
2018/07/02 Javascript
vue用递归组件写树形控件的实例代码
2018/07/19 Javascript
ES6中的迭代器、Generator函数及Generator函数的异步操作方法
2019/05/12 Javascript
JS实现水平遍历和嵌套递归操作示例
2019/08/15 Javascript
解决vue props传Array/Object类型值,子组件报错的情况
2020/11/07 Javascript
[48:22]VGJ.S vs VG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
一个基于flask的web应用诞生(1)
2017/04/11 Python
Python简单实现两个任意字符串乘积的方法示例
2018/04/12 Python
Python使用selenium实现网页用户名 密码 验证码自动登录功能
2018/05/16 Python
Python学习笔记之Zip和Enumerate用法实例分析
2019/08/14 Python
Django框架 信号调度原理解析
2019/09/04 Python
Python3安装pip工具的详细步骤
2019/10/14 Python
py-charm延长试用期限实例
2019/12/22 Python
canvas环形倒计时组件的示例代码
2018/06/14 HTML / CSS
Html5 Canvas动画基础碰撞检测的实现
2018/12/06 HTML / CSS
澳大利亚的奢侈品牌:Oroton
2016/08/26 全球购物
世界上最值得信赖的多日游在线市场:TourRadar
2018/07/20 全球购物
Deichmann英国:德国鞋类零售商
2021/01/30 全球购物
如何用Java判断一个文件或目录是否存在
2012/11/19 面试题
国外的一些J2EE面试题一
2012/10/13 面试题
六年级数学教学反思
2014/02/03 职场文书
财务人员求职自荐书范文
2014/02/10 职场文书
六一节目主持词
2014/04/01 职场文书
市政工程技术专业自荐书
2014/07/06 职场文书
政府会议通知范文
2015/04/15 职场文书