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 基础学习第二弹 类属性和实例属性
Aug 27 Python
在Python3中初学者应会的一些基本的提升效率的小技巧
Mar 31 Python
用Python编写一个简单的俄罗斯方块游戏的教程
Apr 03 Python
详解Python中open()函数指定文件打开方式的用法
Jun 04 Python
Python中生成Epoch的方法
Apr 26 Python
Python实现Pig Latin小游戏实例代码
Feb 02 Python
pandas Dataframe行列读取的实例
Jun 08 Python
如何利用Python模拟GitHub登录详解
Jul 15 Python
python爬取本站电子书信息并入库的实现代码
Jan 20 Python
Python使用qrcode二维码库生成二维码方法详解
Feb 17 Python
Python中flatten( ),matrix.A用法说明
Jul 05 Python
Python 操作SQLite数据库的示例
Oct 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实现链式操作的三种方法详解
2017/11/16 PHP
laravel框架语言包拓展实现方法分析
2019/11/22 PHP
Prototype使用指南之array.js
2007/01/10 Javascript
javascript 获取所有id中包含某关键字的控件的实现代码
2010/11/25 Javascript
js键盘事件的keyCode
2014/07/29 Javascript
JavaScript实现把rgb颜色转换成16进制颜色的方法
2015/06/01 Javascript
解决jQuery uploadify在非IE核心浏览器下无法上传
2015/08/05 Javascript
jquery仿QQ登录账号选择下拉框效果
2016/03/22 Javascript
JS从一组数据中找到指定的单条数据的方法
2016/06/02 Javascript
jQuery Validate让普通按钮触发表单验证的方法
2016/12/15 Javascript
详谈jQuery unbind 删除绑定事件 / 移除标签方法
2017/03/02 Javascript
javascript 中关于array的常用方法详解
2017/05/05 Javascript
关于jQuery库冲突的完美解决办法
2017/05/20 jQuery
vue基于Element构建自定义树的示例代码
2017/09/19 Javascript
webpack4 入门最简单的例子介绍
2018/09/05 Javascript
Vue 实现对quill-editor组件中的工具栏添加title
2020/08/03 Javascript
VUE子组件向父组件传值详解(含传多值及添加额外参数场景)
2020/09/01 Javascript
[01:19:35]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#2Fnatic VS OG第二局
2016/03/05 DOTA
Python3计算三角形的面积代码
2017/12/18 Python
Python 12306抢火车票脚本 Python京东抢手机脚本
2018/02/06 Python
对Tensorflow中的变量初始化函数详解
2018/07/27 Python
python的mysql数据库建立表与插入数据操作示例
2019/09/30 Python
python实现PCA降维的示例详解
2020/02/24 Python
一款纯css3实现的鼠标经过按钮特效教程
2014/11/09 HTML / CSS
Room Mate Hotels美国:西班牙酒店品牌
2018/04/10 全球购物
最好的商品表达自己:Cafepress
2019/09/04 全球购物
说说你所熟悉或听说过的j2ee中的几种常用模式?及对设计模式的一些看法
2012/05/24 面试题
综合素质的自我鉴定
2013/10/07 职场文书
会计自我鉴定
2014/02/04 职场文书
新春寄语大全
2014/04/09 职场文书
学校党支部承诺书
2015/04/30 职场文书
2015年护士节活动策划方案
2015/05/04 职场文书
八年级作文之感悟亲情
2019/11/20 职场文书
JavaScript阻止事件冒泡的方法
2021/12/06 Javascript
Hive导入csv文件示例
2022/06/25 数据库
element tree树形组件回显数据问题解决
2022/08/14 Javascript