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 相关文章推荐
ssh批量登录并执行命令的python实现代码
May 25 Python
使用70行Python代码实现一个递归下降解析器的教程
Apr 17 Python
利用Python抓取行政区划码的方法
Nov 28 Python
Python实现判断字符串中包含某个字符的判断函数示例
Jan 08 Python
numpy向空的二维数组中添加元素的方法
Nov 01 Python
Python requests模块实例用法
Feb 11 Python
谈一谈数组拼接tf.concat()和np.concatenate()的区别
Feb 07 Python
python 对任意数据和曲线进行拟合并求出函数表达式的三种解决方案
Feb 18 Python
python3让print输出不换行的方法
Aug 24 Python
python在linux环境下安装skimage的示例代码
Oct 14 Python
变长双向rnn的正确使用姿势教学
May 31 Python
Python Pandas数据分析之iloc和loc的用法详解
Nov 11 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 $_SERVER详解
2009/01/16 PHP
PHP 在5.1.* 和5.2.*之间 PDO数据库操作中的不同之处小结
2012/03/07 PHP
PHP之生成GIF动画的实现方法
2013/06/07 PHP
PHP中判断变量为空的几种方法小结
2013/11/12 PHP
php发送post请求的三种方法
2014/02/11 PHP
php 5.4 全新的代码复用Trait详解
2017/01/05 PHP
jQuery插件开发详细教程
2014/06/06 Javascript
SuperSlide标签切换、焦点图多种组合插件
2015/03/14 Javascript
html5+javascript实现简单上传的注意细节
2016/04/18 Javascript
基于Bootstrap+jQuery.validate实现表单验证
2016/05/30 Javascript
JS两个数组比较,删除重复值的巧妙方法(推荐)
2016/06/03 Javascript
js实现简单的计算器功能
2017/01/16 Javascript
js实现省份下拉菜单效果
2017/02/15 Javascript
Node.js 使用流实现读写同步边读边写功能
2017/09/11 Javascript
小程序分享模块超级详解(推荐)
2019/04/10 Javascript
微信小程序引入模块中wxml、wxss、js的方法示例
2019/08/09 Javascript
微信小程序webview组件交互,内联h5页面并网页实现微信支付实现解析
2019/08/16 Javascript
bootstrapValidator表单校验、更改状态、新增、移除校验字段的实例代码
2020/05/19 Javascript
vue的hash值原理也是table切换实例代码
2020/12/14 Vue.js
python使用正则表达式检测密码强度源码分享
2014/06/11 Python
Python利用operator模块实现对象的多级排序详解
2017/05/09 Python
python3.4下django集成使用xadmin后台的方法
2017/08/15 Python
Python基于pycrypto实现的AES加密和解密算法示例
2018/04/10 Python
Django之无名分组和有名分组的实现
2019/04/16 Python
python fuzzywuzzy模块模糊字符串匹配详细用法
2019/08/29 Python
Python3 全自动更新已安装的模块实现
2020/01/06 Python
python使用openpyxl操作excel的方法步骤
2020/05/28 Python
html5利用canvas实现颜色容差抠图功能
2019/12/23 HTML / CSS
Myprotein芬兰官网:欧洲第一运动营养品牌
2019/05/05 全球购物
台湾演唱会订票网站:StubHub台湾
2019/06/11 全球购物
医药专业应届毕业生求职信范文
2014/01/01 职场文书
副厂长岗位职责
2014/02/02 职场文书
高一军训的心得体会
2014/09/01 职场文书
小学生运动会通讯稿
2014/09/23 职场文书
vue route新窗口跳转页面并且携带与接收参数
2022/04/10 Vue.js
《英雄联盟》2022日蚀、月蚀皮肤演示 黑潮亚索曝光
2022/04/13 其他游戏