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以并发方式编写高性能端口扫描器的方法
Jun 14 Python
微信跳一跳python代码实现
Jan 05 Python
python通过elixir包操作mysql数据库实例代码
Jan 31 Python
python 文件查找及内容匹配方法
Oct 25 Python
python 图像平移和旋转的实例
Jan 10 Python
Python开发之Nginx+uWSGI+virtualenv多项目部署教程
May 13 Python
使用python的pyplot绘制函数实例
Feb 13 Python
matlab、python中矩阵的互相导入导出方式
Jun 01 Python
Python with语句用法原理详解
Jul 03 Python
Python中qutip用法示例详解
Oct 02 Python
python实现学生通讯录管理系统
Feb 25 Python
手把手教你实现PyTorch的MNIST数据集
Jun 28 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
实用函数3
2007/11/08 PHP
php使用ICQ网关发送手机短信
2013/10/30 PHP
php自动识别文件编码并转换为UTF-8的方法
2014/06/12 PHP
详解PHP安装mysql.so扩展的方法
2016/12/31 PHP
用javascript实现页面打印的三种方法
2007/03/05 Javascript
JS 类型转换常见方法小结
2010/05/31 Javascript
ExtJs设置GridPanel表格文本垂直居中示例
2013/07/15 Javascript
可兼容IE的获取及设置cookie的jquery.cookie函数方法
2013/09/02 Javascript
js之事件冒泡和事件捕获详细介绍
2013/10/28 Javascript
Knockout数组(observable)使用详解示例
2013/11/15 Javascript
探讨jQuery的ajax使用场景(c#)
2013/12/03 Javascript
JS函数重载的解决方案
2014/05/13 Javascript
浅谈javascript中的三种弹窗
2016/10/21 Javascript
进阶之初探nodeJS
2017/01/24 NodeJs
微信小程序 在线支付功能的实现
2017/03/14 Javascript
Vue框架中正确引入JS库的方法介绍
2017/07/30 Javascript
浅谈vue中数据双向绑定的实现原理
2017/09/14 Javascript
AnglarJs中的上拉加载实现代码
2018/02/08 Javascript
详解 vue better-scroll滚动插件排坑
2018/02/08 Javascript
实例详解Node.js 函数
2018/06/10 Javascript
微信小程序云开发(数据库)详解
2019/05/17 Javascript
JS实现网站吸顶条
2020/01/08 Javascript
js实现视图和数据双向绑定的方法分析
2020/02/05 Javascript
[14:00]DOTA2国际邀请赛史上最长大战 赛后专访B神
2013/08/10 DOTA
[45:25]完美世界DOTA2联赛循环赛 PXG vs IO 第一场 11.06
2020/11/09 DOTA
python写入已存在的excel数据实例
2018/05/03 Python
pandas 条件搜索返回列表的方法
2018/10/30 Python
python sqlite的Row对象操作示例
2019/09/11 Python
python创建ArcGIS shape文件的实现
2019/12/06 Python
pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)
2020/06/24 Python
python绘图模块之利用turtle画图
2021/02/12 Python
英国体育器材进口商店:UK Sport Imports
2017/03/14 全球购物
排查整治工作方案
2014/06/09 职场文书
2014年党建工作总结
2014/11/11 职场文书
2019年大学生学年自我鉴定!
2019/03/25 职场文书
小学生一年级(书信作文)
2019/08/13 职场文书