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获取从命令行输入数字的方法
Apr 29 Python
Python实现识别手写数字大纲
Jan 29 Python
python 按照固定长度分割字符串的方法小结
Apr 30 Python
用Django写天气预报查询网站
Oct 21 Python
解决python测试opencv时imread导致的错误问题
Jan 26 Python
Python实现计算文件MD5和SHA1的方法示例
Jun 11 Python
Python中判断子串存在的性能比较及分析总结
Jun 23 Python
python中的colorlog库使用详解
Jul 05 Python
python elasticsearch环境搭建详解
Sep 02 Python
django2.2 和 PyMySQL版本兼容问题
Feb 17 Python
Python监听键盘和鼠标事件的示例代码
Nov 18 Python
pandas中pd.groupby()的用法详解
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编程与应用
2006/10/09 PHP
php中使用redis队列操作实例代码
2013/02/07 PHP
Mysql的Root密码忘记,查看或修改的解决方法(图文介绍)
2013/06/14 PHP
php中filter函数验证、过滤用户输入的数据
2014/01/13 PHP
PHP通过内置函数memory_get_usage()获取内存使用情况
2014/11/20 PHP
laravel框架模型中非静态方法也能静态调用的原理分析
2019/11/23 PHP
PHP 出现 http500 错误的解决方法
2021/03/09 PHP
javascript 24小时弹出一次的代码(利用cookies)
2009/09/03 Javascript
jQuery中element选择器用法实例
2014/12/29 Javascript
使用C++为node.js写扩展模块
2015/04/22 Javascript
javascript实现3D切换焦点图
2015/10/16 Javascript
JavaScript如何动态创建table表格
2020/08/02 Javascript
详解Javascript中的Object对象
2016/02/28 Javascript
JavaScript每天必学之数组和对象部分
2016/09/17 Javascript
chorme 浏览器记住密码后input黄色背景处理方法(两种)
2017/11/22 Javascript
代码详解javascript模块加载器
2018/03/04 Javascript
你可能不知道的CORS跨域资源共享
2019/03/13 Javascript
微信小程序实现一张或多张图片上传(云开发)
2019/09/25 Javascript
纯js实现无缝滚动功能代码实例
2020/02/21 Javascript
JavaScript自定义超时API代码实例
2020/04/30 Javascript
Python实现类继承实例
2014/07/04 Python
详细讲解Python中的文件I/O操作
2015/05/24 Python
Python中使用bidict模块双向字典结构的奇技淫巧
2016/07/12 Python
Python实现去除图片中指定颜色的像素功能示例
2019/04/13 Python
在django admin中添加自定义视图的例子
2019/07/26 Python
python利用itertools生成密码字典并多线程撞库破解rar密码
2019/08/12 Python
在Pytorch中使用样本权重(sample_weight)的正确方法
2019/08/17 Python
python 统计文件中的字符串数目示例
2019/12/24 Python
通过 Python 和 OpenCV 实现目标数量监控
2020/01/05 Python
Python在字符串中处理html和xml的方法
2020/07/31 Python
什么是测试驱动开发(TDD)
2012/02/15 面试题
会计电算化大学生职业规划书
2014/02/05 职场文书
大专生自荐书范文
2014/06/22 职场文书
入党积极分子自我批评思想汇报
2014/10/10 职场文书
2015年度团总支工作总结
2015/04/23 职场文书
pytorch fine-tune 预训练的模型操作
2021/06/03 Python