Python中对象的引用与复制代码示例


Posted in Python onDecember 04, 2017

可以说Python没有赋值,只有引用。你这样相当于创建了一个引用自身的结构,所以导致了无限循环。为了理解这个问题,有个基本概念需要搞清楚。

Python没有「变量」,我们平时所说的变量其实只是「标签」,是引用。

python中,"a=b"表示的是对象a引用对象b,对象a本身没有单独分配内存空间(重要:不是复制!),它指向计算机中存储对象b的内存。因此,要想将一个对象复制为另一个对象,不能简单地用等号操作,要使用其它的方法。如序列类的对象是(列表、元组)要使用切片操作符(即':')来做复制。

在python进行像b = a这样的赋值时,只会创建一个对a的新引用,使a的引用计数加1,而不会创建新的对象:

>>> a = 'xyz'
>>> import sys
>>> sys.getrefcount(a)
3
>>> b = a
>>> sys.getrefcount(b)
4
>>> id(a)
88292288L
>>> id(b)
88292288L

这样,当引用的对象是可变对象的时候(列表,字典,可变集合等),会产生意料之外的行为:

>>> a = [1, 2, 3, 4]
>>> b = a
>>> b.append(5)
>>> a
[1, 2, 3, 4, 5]

因为a和b引用的是同一对象,改变其中一个,另外一个也会随之改变。当我们想建立一个副本而不是引用时,可以复制对象。

复制对象一般使用copy模块:

>>> a = [1, 2, 3, 4]
>>> import copy
>>> b = copy.copy(a)
>>> b.append(5)
>>> b
[1, 2, 3, 4, 5]
>>> a
[1, 2, 3, 4]

这样就可以了,但这种复制是一种浅复制,复制的新对象中包含的是对原始对象中的项的引用,如果对象的项为可变对象,也会产生不可控行为:

>>> a = [1, [1, 2]]
>>> b = copy.copy(a)
>>> b[1].append(3)
>>> b
[1, [1, 2, 3]]
>>> a
[1, [1, 2, 3]]

这时候就要使用深复制了。深复制将创建一个新对象,并递归地复制它所包含的所有对象:

>>> a = [1, [1, 2]]
>>> b = copy.deepcopy(a)
>>> b[1].append(3)
>>> b
[1, [1, 2, 3]]
>>> a
[1, [1, 2]]

对于不可改变的对象而言(字符串,数字,元组)等,没有必要拷贝,因为它们是不可改变的,不用担心会不经意间改动了它们。拷贝操作也只会得到原对象:

>>> a = (1, 2, 3)
>>> b = copy.copy(a)
>>> a is b
True

对于可变对象来(列表,字典,可变集合)来说,可以分别使用内置函数list(),dict(),set()来进行浅复制,速度是比使用copy模块快的。

列表也可以使用切片进行浅复制:

>>> a = [1, 2, 3, 4]
>>> b = a[:]
>>> a is b
False
>>> b
[1, 2, 3, 4]

对序列数据类型(字符串,列表,元组)进行*操作时,也仅仅是复制了对象中项的引用,如果使用*创建一个多维列表:

>>> a = [1, 2, 3]
>>> b = [a]
>>> c = b * 3
>>> a.append(4)
>>> c
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]

最好是在列表推导中使用浅复制来创建多维列表,可以避免隐式的引用共享:

>>> a = [1, 2, 3]
>>> c = [list(a) for i in range(3)]
>>> a.append(4)
>>> c
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]

总结

以上就是本文关于Python中对象的引用与复制代码示例的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。

Python 相关文章推荐
python海龟绘图实例教程
Jul 24 Python
Python基于回溯法解决01背包问题实例
Dec 06 Python
python中使用xlrd读excel使用xlwt写excel的实例代码
Jan 31 Python
Python程序运行原理图文解析
Feb 10 Python
Python里字典的基本用法(包括嵌套字典)
Feb 27 Python
Django获取应用下的所有models的例子
Aug 30 Python
使用python远程操作linux过程解析
Dec 04 Python
Django Serializer HiddenField隐藏字段实例
Mar 31 Python
Python flask框架实现浏览器点击自定义跳转页面
Jun 04 Python
Python脚本如何在bilibili中查找弹幕发送者
Jun 04 Python
Win10下用Anaconda安装TensorFlow(图文教程)
Jun 18 Python
Python实战实现爬取天气数据并完成可视化分析详解
Jun 16 Python
Python3 Random模块代码详解
Dec 04 #Python
利用python爬取斗鱼app中照片方法实例
Dec 03 #Python
CentOS 6.5中安装Python 3.6.2的方法步骤
Dec 03 #Python
python3利用smtplib通过qq邮箱发送邮件方法示例
Dec 03 #Python
Python中类的初始化特殊方法
Dec 01 #Python
Python抓取框架Scrapy爬虫入门:页面提取
Dec 01 #Python
Python实现调度算法代码详解
Dec 01 #Python
You might like
php你的验证码安全码?
2007/01/02 PHP
用php解析html的实现代码
2011/08/08 PHP
ThinkPHP中公共函数路径和配置项路径的映射分析
2014/11/22 PHP
PHP编写文件多服务器同步程序
2016/07/02 PHP
php字符集转换
2017/01/23 PHP
PHP文字转图片功能原理与实现方法分析
2017/08/31 PHP
自写的利用PDO对mysql数据库增删改查操作类
2018/02/19 PHP
PHP7 错误处理机制修改
2021/03/09 PHP
“不能执行已释放的Script代码”错误的原因及解决办法
2007/09/09 Javascript
关于jquery ajax 调用带参数的webservice返回XML数据一个小细节
2012/07/31 Javascript
用JQuery在网页中实现分隔条功能的代码
2012/08/09 Javascript
jQuery阻止同类型事件小结
2013/04/19 Javascript
回车直接实现点击某按钮的效果即触发单击事件
2014/02/27 Javascript
js实现在同一窗口浏览图片
2014/09/17 Javascript
深入理解JavaScript系列(30):设计模式之外观模式详解
2015/03/03 Javascript
基于jQuery实现表格的排序
2016/12/02 Javascript
node.js中fs.stat与fs.fstat的区别详解
2017/06/01 Javascript
3分钟了解vue数据劫持的原理实现
2019/05/01 Javascript
Smartour 让网页导览变得更简单(推荐)
2019/07/19 Javascript
vuejs实现下拉框菜单选择
2020/10/23 Javascript
vue实现标签云效果的示例
2020/11/09 Javascript
vue中封装axios并实现api接口的统一管理
2020/12/25 Vue.js
[52:03]Secret vs VG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
Python 除法小技巧
2008/09/06 Python
Python自动化部署工具Fabric的简单上手指南
2016/04/19 Python
python2与python3的print及字符串格式化小结
2018/11/30 Python
基于Python获取城市近7天天气预报
2019/11/26 Python
python实现滑雪者小游戏
2020/02/22 Python
查看jupyter notebook每个单元格运行时间实例
2020/04/22 Python
澳大利亚冲浪和时尚服装网上购物:SurfStitch
2017/07/29 全球购物
物业管理个人自我评价
2013/11/08 职场文书
外贸采购员岗位职责
2014/03/08 职场文书
“四风”查摆问题自我剖析材料
2014/09/27 职场文书
安徽导游词
2015/02/12 职场文书
入党转正介绍人意见
2015/06/03 职场文书
三好学生主要事迹怎么写
2015/11/03 职场文书