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 相关文章推荐
Android模拟器无法启动,报错:Cannot set up guest memory ‘android_arm’ Invalid argument的解决方法
Jul 01 Python
TensorFlow实现Batch Normalization
Mar 08 Python
python 借助numpy保存数据为csv格式的实现方法
Jul 04 Python
解决python3.5 正常安装 却不能直接使用Tkinter包的问题
Feb 22 Python
从列表或字典创建Pandas的DataFrame对象的方法
Jul 06 Python
python pickle存储、读取大数据量列表、字典数据的方法
Jul 07 Python
Python定时任务工具之APScheduler使用方式
Jul 24 Python
python读写csv文件并增加行列的实例代码
Aug 01 Python
windows 10 设定计划任务自动执行 python 脚本的方法
Sep 11 Python
你还在@微信官方?聊聊Python生成你想要的微信头像
Sep 25 Python
Python字典的概念及常见应用实例详解
Oct 30 Python
七个Python必备的GUI库
Apr 27 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 伪静态隐藏传递参数名的四种方法
2010/02/22 PHP
关于php操作mysql执行数据库查询的一些常用操作汇总
2013/06/24 PHP
php使用curl抓取qq空间的访客信息示例
2014/02/28 PHP
thinkPHP3.x常量整理(预定义常量/路径常量/系统常量)
2016/05/20 PHP
jQuery学习笔记之jQuery构建函数的7种方法
2014/06/03 Javascript
JS实现课堂随机点名和顺序点名
2017/03/09 Javascript
js 函数式编程学习笔记
2017/03/25 Javascript
JavaScrip关于创建常量的知识点
2017/12/07 Javascript
详解在vue-cli中使用graphql即vue-apollo的用法
2018/09/08 Javascript
Vue弹出菜单功能的实现代码
2018/09/12 Javascript
深入理解Node内建模块和对象
2019/03/12 Javascript
vue使用原生swiper代码实例
2020/02/05 Javascript
vue radio单选框,获取当前项(每一项)的value值操作
2020/09/10 Javascript
Openlayers实现距离面积测量
2020/09/28 Javascript
Python编程之变量赋值操作实例分析
2017/07/24 Python
Python PyQt5实现的简易计算器功能示例
2017/08/23 Python
Python3 加密(hashlib和hmac)模块的实现
2017/11/23 Python
python看某个模块的版本方法
2018/10/16 Python
Django 多环境配置详解
2019/05/14 Python
python程序运行进程、使用时间、剩余时间显示功能的实现代码
2019/07/11 Python
PyQt5使用QTimer实现电子时钟
2019/07/29 Python
django框架cookie和session用法实例详解
2019/12/10 Python
使用PyQt5实现图片查看器的示例代码
2020/04/21 Python
pip install命令安装扩展库整理
2021/03/02 Python
Unix里面如何在后台运行程序
2016/10/14 面试题
高中毕业生个人自我鉴定
2013/11/24 职场文书
数据保密承诺书
2014/06/03 职场文书
体育节口号
2014/06/19 职场文书
干部作风建设个人剖析材料
2014/10/11 职场文书
党的群众路线教育实践活动党员个人整改措施
2014/10/27 职场文书
委托书格式要求
2015/01/28 职场文书
公司地址变更通知
2015/04/25 职场文书
中国梦党课学习心得体会
2016/01/05 职场文书
高一作文之暖冬
2019/11/09 职场文书
如何用threejs实现实时多边形折射
2021/05/07 Javascript
Python数据可视化之绘制柱状图和条形图
2021/05/25 Python