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赋值操作方法分享
Mar 23 Python
Python检测生僻字的实现方法
Oct 23 Python
python 将列表中的字符串连接成一个长路径的方法
Oct 23 Python
对python3 中方法各种参数和返回值详解
Dec 15 Python
实例讲解Python中浮点型的基本内容
Feb 11 Python
python使用itchat模块给心爱的人每天发天气预报
Nov 25 Python
python批量处理txt文件的实例代码
Jan 13 Python
PyTorch实现AlexNet示例
Jan 14 Python
python实现交并比IOU教程
Apr 16 Python
Python基于jieba, wordcloud库生成中文词云
May 13 Python
Python二元算术运算常用方法解析
Sep 15 Python
python从Oracle读取数据生成图表
Oct 14 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
PHP自定义大小验证码的方法详解
2013/06/07 PHP
PHP图片处理之使用imagecopyresampled函数裁剪图片例子
2014/11/19 PHP
phalcon框架使用指南
2016/02/23 PHP
Yii2增删改查之查询 where参数详细介绍
2016/08/08 PHP
php array_values 返回数组的所有值详解及实例
2016/11/12 PHP
PHP中让json_encode不自动转义斜杠“/”的方法
2017/02/28 PHP
thinkPHP5 tablib标签库自定义方法详解
2017/05/10 PHP
PHP实现统计所有字符在字符串中出现次数的方法
2017/10/17 PHP
php中用unset销毁变量并释放内存
2020/05/10 PHP
js Form.elements[i]的使用实例
2011/11/13 Javascript
Javascript对象属性方法汇总
2013/11/21 Javascript
setTimeout()递归调用不加引号出错的解决方法
2014/09/05 Javascript
js实现可折叠展开的手风琴菜单效果
2015/09/07 Javascript
JavaScript知识点整理
2015/12/09 Javascript
在js中实现邮箱格式的验证方法(推荐)
2016/10/24 Javascript
AngularJS ng-template寄宿方式用法分析
2016/11/07 Javascript
微信小程序 获取session_key和openid的实例
2017/08/17 Javascript
express如何使用session与cookie的方法
2018/01/30 Javascript
使用react实现手机号的数据同步显示功能的示例代码
2018/04/03 Javascript
php中and 和 &&出坑指南
2018/07/13 Javascript
JS div匀速移动动画与变速移动动画代码实例
2019/03/26 Javascript
JS使用cookie保存用户登录信息操作示例
2019/05/30 Javascript
Vue移动端实现图片上传及超过1M压缩上传
2019/12/23 Javascript
[08:38]DOTA2-DPC中国联赛 正赛 VG vs Elephant 选手采访
2021/03/11 DOTA
Python使用scrapy采集数据时为每个请求随机分配user-agent的方法
2015/04/08 Python
python中list列表的高级函数
2016/05/17 Python
Python实现动态图解析、合成与倒放
2018/01/18 Python
Python OpenCV获取视频的方法
2018/02/28 Python
详解python3 + Scrapy爬虫学习之创建项目
2019/04/12 Python
Python pandas 列转行操作详解(类似hive中explode方法)
2020/05/18 Python
关于python的缩进规则的知识点详解
2020/06/22 Python
利用scikitlearn画ROC曲线实例
2020/07/02 Python
css3实现3D色子翻转特效
2014/12/23 HTML / CSS
武汉瑞得软件笔试题
2015/10/27 面试题
党校自我鉴定范文
2013/10/02 职场文书
运动会跳远加油稿
2014/02/20 职场文书