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/ironpython:从入门到精通
Oct 02 Python
Python字符串转换成浮点数函数分享
Jul 24 Python
在PyCharm中批量查找及替换的方法
Jan 20 Python
Python 隐藏输入密码时屏幕回显的实例
Feb 19 Python
Python3.5多进程原理与用法实例分析
Apr 05 Python
Python使用线程来接收串口数据的示例
Jul 02 Python
django项目中使用手机号登录的实例代码
Aug 15 Python
Python绘制热力图示例
Sep 27 Python
Python图像处理库PIL中图像格式转换的实现
Feb 26 Python
Windows+Anaconda3+PyTorch+PyCharm的安装教程图文详解
Apr 03 Python
keras中的loss、optimizer、metrics用法
Jun 15 Python
pytorch通过训练结果的复现设置随机种子
Jun 01 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中Http协议post请求参数
2015/11/02 PHP
PHP常见数组函数用法小结
2016/03/21 PHP
yii框架搜索分页modle写法
2016/12/19 PHP
php数组指针函数功能及用法示例
2020/02/11 PHP
JavaScript 读取元素的CSS信息的代码
2010/02/07 Javascript
浅析JQuery UI Dialog的样式设置问题
2013/12/18 Javascript
js 与 php 通过json数据进行通讯示例
2014/03/26 Javascript
javascript关于open.window子页面执行完成后刷新父页面的问题分析
2015/04/27 Javascript
javascript中使用正则表达式清理table样式的代码
2020/04/01 Javascript
jQuery实现根据滚动条位置加载相应内容功能
2016/07/18 Javascript
JavaScript代码执行的先后顺序问题
2017/10/29 Javascript
karma+webpack搭建vue单元测试环境的方法示例
2018/05/24 Javascript
Node.js动手撸一个静态资源服务器的方法
2019/03/09 Javascript
layui 根据后台数据动态创建下拉框并同时默认选中的实例
2019/09/02 Javascript
微信小程序 点击切换样式scroll-view实现代码实例
2019/10/11 Javascript
vue 使用async写数字动态加载效果案例
2020/07/18 Javascript
用python结合jieba和wordcloud实现词云效果
2017/09/05 Python
详解Python读取yaml文件多层菜单
2019/03/23 Python
python判断文件夹内是否存在指定后缀文件的实例
2019/06/10 Python
微信小程序python用户认证的实现
2019/07/29 Python
Python range、enumerate和zip函数用法详解
2019/09/11 Python
pandas按行按列遍历Dataframe的几种方式
2019/10/23 Python
Pandas时间序列重采样(resample)方法中closed、label的作用详解
2019/12/10 Python
pyqt5数据库使用详细教程(打包解决方案)
2020/03/25 Python
Python定义一个函数的方法
2020/06/15 Python
安装pyinstaller遇到的各种问题(小结)
2020/11/20 Python
HTML5 CSS3实现一个精美VCD包装盒个性幻灯片案例
2014/06/16 HTML / CSS
JINS眼镜官方网站:日本最大的眼镜邮购
2016/10/14 全球购物
巴西最大的家电和百货零售商:Casas Bahia
2016/11/22 全球购物
迪士尼英国官方商店:shopDisney UK
2019/09/21 全球购物
The Outnet亚太地区:折扣设计师时装店
2019/12/05 全球购物
灵泰克Java笔试题
2016/01/09 面试题
优秀大学生职业生涯规划书
2014/02/27 职场文书
乡镇领导干部个人对照检查材料思想汇报
2014/09/23 职场文书
教师批评与自我批评(群众路线)
2014/10/15 职场文书
Html5获取用户当前位置的几种方式
2022/01/18 HTML / CSS