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实现将n个点均匀地分布在球面上的方法
Mar 12 Python
举例讲解Python中的死锁、可重入锁和互斥锁
Nov 05 Python
Python random模块用法解析及简单示例
Dec 18 Python
python实现数独游戏 java简单实现数独游戏
Mar 30 Python
python多维数组切片方法
Apr 13 Python
python使用matplotlib画饼状图
Sep 25 Python
对python中UDP,socket的使用详解
Aug 22 Python
Python使用get_text()方法从大段html中提取文本的实例
Aug 27 Python
python批量替换文件名中的共同字符实例
Mar 05 Python
浅谈django channels 路由误导
May 28 Python
python如何操作mysql
Aug 17 Python
浅谈Python从全局与局部变量到装饰器的相关知识
Jun 21 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面向对象的方法重载两种版本比较
2008/09/08 PHP
基于PHP实现栈数据结构和括号匹配算法示例
2017/08/10 PHP
Jquery插件分享之气泡形提示控件grumble.js
2014/05/20 Javascript
我的Node.js学习之路(二)NPM模块管理
2014/07/06 Javascript
Windows8下搭建Node.js开发环境教程
2014/09/03 Javascript
在Html中使用Requirejs进行模块化开发实例详解
2016/04/15 Javascript
获取input标签的所有属性的方法
2016/06/28 Javascript
AngularJS基础 ng-srcset 指令简单示例
2016/08/03 Javascript
Vue中的Vux配置指南
2017/12/08 Javascript
通过js动态创建标签,并设置属性方法
2018/02/24 Javascript
vue.js使用v-model实现父子组件间的双向通信示例
2020/02/05 Javascript
python根据路径导入模块的方法
2014/09/30 Python
让 python 命令行也可以自动补全
2014/11/30 Python
详解Python中类的定义与使用
2017/04/11 Python
Python实现合并同一个文件夹下所有txt文件的方法示例
2018/04/26 Python
python版本单链表实现代码
2018/09/28 Python
Python 脚本实现淘宝准点秒杀功能
2019/11/13 Python
python循环输出三角形图案的例子
2019/11/22 Python
python实现超级马里奥
2020/03/18 Python
Python字符串split及rsplit方法原理详解
2020/06/29 Python
html5启动原生APP总结
2020/07/03 HTML / CSS
英国广泛的照明产品网站:Lights4living
2018/01/28 全球购物
Daisy London官网:英国最大的首饰集团IBB旗下
2019/02/28 全球购物
Ootori在线按摩椅店:一家专业的按摩椅制造商
2019/04/10 全球购物
阿姆斯特丹城市卡:Amsterdam Pass
2019/12/01 全球购物
俄罗斯童装网上商店:BebaKids
2020/06/06 全球购物
教师应聘个人求职信
2013/12/10 职场文书
校园学雷锋活动月总结
2014/03/09 职场文书
政治学求职信
2014/06/03 职场文书
乡镇爱国卫生月活动总结
2014/06/25 职场文书
2014年企业团支部工作总结
2014/12/10 职场文书
九华山导游词
2015/02/03 职场文书
干货干货!2019最新优秀创业计划书
2019/03/21 职场文书
python某漫画app逆向
2021/03/31 Python
MySQL外键约束(Foreign Key)案例详解
2022/06/28 MySQL
nginx之内存池的实现
2022/06/28 Servers