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 图片验证码代码
Dec 07 Python
浅析Python中的for 循环
Jun 09 Python
Python的包管理器pip更换软件源的方法详解
Jun 20 Python
Python yield与实现方法代码分析
Feb 06 Python
python清除函数占用的内存方法
Jun 25 Python
Python 函数用法简单示例【定义、参数、返回值、函数嵌套】
Sep 20 Python
Python使用grequests(gevent+requests)并发发送请求过程解析
Sep 25 Python
flask框架自定义过滤器示例【markdown文件读取和展示功能】
Nov 08 Python
python shapely.geometry.polygon任意两个四边形的IOU计算实例
Apr 12 Python
python中os包的用法
Jun 01 Python
用Python selenium实现淘宝抢单机器人
Jun 18 Python
python中的sys模块和os模块
Mar 20 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
咖啡是不是喝了会上瘾?咖啡是必须品吗!
2021/03/04 新手入门
一些关于PHP的知识
2006/11/17 PHP
php巧获服务器端信息
2006/12/06 PHP
javascript 写的一个简单的timer
2009/07/30 Javascript
jquery实现表单验证并阻止非法提交
2015/07/09 Javascript
js文字横向滚动特效
2015/11/11 Javascript
微信小程序之picker日期和时间选择器
2017/02/09 Javascript
利用Chrome DevTools直接调试Node.js和JavaScript的方法详解(并行)
2017/02/16 Javascript
vue.js移动端app实战1:初始配置详解
2017/07/24 Javascript
JQuery EasyUI 结合ztrIee的后台页面开发实例
2017/09/01 jQuery
关于Vue组件库开发详析
2018/07/01 Javascript
微信小程序canvas绘制圆角base64图片的实现
2019/08/18 Javascript
vue router-link 默认a标签去除下划线的实现
2020/11/06 Javascript
[14:51]DOTA2 HEROS教学视频教你分分钟做大人-卓尔游侠
2014/06/13 DOTA
python自定义异常实例详解
2017/07/11 Python
Python使用asyncio包处理并发详解
2017/09/09 Python
Python基于贪心算法解决背包问题示例
2017/11/27 Python
利用Python如何生成hash值示例详解
2017/12/20 Python
Python使用爬虫抓取美女图片并保存到本地的方法【测试可用】
2018/08/30 Python
让你的Python代码实现类型提示功能
2019/11/19 Python
Python数据正态性检验实现过程
2020/04/18 Python
从零开始的TensorFlow+VScode开发环境搭建的步骤(图文)
2020/08/31 Python
7款设计巧妙的css3飘带状3D立体效果的导航菜单和表单窗口
2013/02/04 HTML / CSS
详解基于 Canvas 手撸一个六边形能力图
2019/09/02 HTML / CSS
突袭HTML5之Javascript API扩展3—本地存储全新体验
2013/01/31 HTML / CSS
台湾线上百货零售购物平台:friDay购物
2017/08/18 全球购物
市场营销专业个人自荐信格式
2013/09/21 职场文书
办公室内勤工作职责
2013/12/11 职场文书
国家助学金获奖感言
2014/01/31 职场文书
《匆匆》教学反思
2014/02/22 职场文书
研讨会主持词
2014/04/02 职场文书
服务承诺口号
2014/05/22 职场文书
群众路线个人对照检查材料2014
2014/09/26 职场文书
《惊弓之鸟》教学反思
2016/02/20 职场文书
研究生毕业登记表的自我鉴定范文
2019/07/15 职场文书
python 提取html文本的方法
2021/05/20 Python