Python中的引用和拷贝浅析


Posted in Python onNovember 22, 2014

If an object's value can be modified, the object is said to be mutable. If the value cannot be modified,the object is said to be immutable.

mutable 可变类型,例如 list,set,自定义类型(等价于C#中的引用类型);

immutable 不可变类型,例如string,numbers等(等价于C#中的值类型);

一、引用和拷贝(references and copies)

当程序中使用=赋值操作符时,例如a=b,

对于不可变的对象,a作为b的一个拷贝被创建,a和b将指向不同的内存地址,a和b相互独立。

def TestCopy():

    a = 10

    b = a

    a =20

    print (b) #b still is 10

但是对于可变的对象,a作为b的一个引用被创建,a和b的元素公用相同的内存地址,a和b的元素共享。
def TestRef():

    a=[1,2,3,4]

    b=a   #b is a reference to a

    print (b is a) # True

    b[2] = -100 #change an element in b

    print (a) # a also changed to [1,2,-100,4]

二、深拷贝和浅拷贝(shallow copy and deep copy)

为了避免可变对象指向同一个对象,必须创建一个新的拷贝,而不是引用。
在python中可以对容器对象(例如lists和dictionaries)使用两种拷贝:浅拷贝和深拷贝。
 
浅拷贝创建一个新的对象,但是使用原来对象的元素的引用(如果是不变类型,相当于是拷贝)来填充新对象。可以使用copy.copy()来实现浅拷贝。

def TestShallowCopy():

    a = [ 1, 2, [3,4] ]

    b = list(a) # create a shallow copy of a

    print (b is a) #False

    b.append(100) #append element to b

    print (b)

    print (a) # a is unchanged

    b[2][0] = -100 # modify an element inside b

    print (b)

    print (a)  # a is changed

在这个例子中,a和b共享相同的可变元素。所以修改其中一个list对象中的元素,另一个list对象也会被修改。

深拷贝创建一个新的对象,同时递归地拷贝对象所包含的所有的元素。可以使用copy.deepcopy()来实现深拷贝。

def TestDeepCopy():

  import copy

  a = [1, 2, [3, 4]]

  b = copy.deepcopy(a)

  b[2][0] = -100

  print (b)  # b is changed

  print (a)  # a is unchanged

在这个例子中,a和b是对立的list对象,且他们的元素也相互独立。

三、引用计数和垃圾回收

python中的所有的对象都是引用计数的,一个对象赋值或加入容器时,它的引用计数就会自增,当使用del时或变量赋值为其他值时,引用计数就会自减,当引用计数为0时,python的垃圾回收器就会回收该变量。

def TestGarbageCollection():

  import sys

  print(sys.getrefcount(37))

  a = 37 # Creates an object with value 37

  print(sys.getrefcount(37))

  b = a # Increases reference count on 37

  print(sys.getrefcount(37))

  c = []

  c.append(b) # Increases reference count on 37

  print(sys.getrefcount(37))

  del a # Decrease reference count of 37

  print(sys.getrefcount(37))

  b = 42 # Decrease reference count of 37

  print(sys.getrefcount(37))

  c[0] = 2.0 # Decrease reference count of 37

  print(sys.getrefcount(37)) 

  

TestGarbageCollection()

运行结果为:

11

12

13

14

13

12

11

为啥一上来就有11个引用了呢?谁知道?
Python 相关文章推荐
python3图片转换二进制存入mysql
Dec 06 Python
python sort、sorted高级排序技巧
Nov 21 Python
Python用threading实现多线程详解
Feb 03 Python
Python编程实现删除VC临时文件及Debug目录的方法
Mar 22 Python
Python中的id()函数指的什么
Oct 17 Python
python实现K最近邻算法
Jan 29 Python
Python的CGIHTTPServer交互实现详解
Feb 08 Python
python生成lmdb格式的文件实例
Nov 08 Python
Python设计模式之组合模式原理与用法实例分析
Jan 11 Python
利用python、tensorflow、opencv、pyqt5实现人脸实时签到系统
Sep 25 Python
Python调用接口合并Excel表代码实例
Mar 31 Python
Django中Aggregation聚合的基本使用方法
Jul 09 Python
python实现的文件夹清理程序分享
Nov 22 #Python
Python判断操作系统类型代码分享
Nov 22 #Python
python logging类库使用例子
Nov 22 #Python
Python中模拟enum枚举类型的5种方法分享
Nov 22 #Python
Python读写Excel文件方法介绍
Nov 22 #Python
Python中的包和模块实例
Nov 22 #Python
Python动态加载模块的3种方法
Nov 22 #Python
You might like
PHP采集相关教程之一 CURL函数库
2010/02/15 PHP
ThinkPHP3.2.2的插件控制器功能简述
2014/07/09 PHP
php获取url参数方法总结
2014/11/13 PHP
php上传图片并压缩的实现方法
2015/12/22 PHP
使用PHPExcel实现数据批量导出为excel表格的方法(必看)
2017/06/09 PHP
swoole_process实现进程池的方法示例
2018/10/29 PHP
PHP PDOStatement::debugDumpParams讲解
2019/01/30 PHP
Laravel框架实现文件上传的方法分析
2019/09/29 PHP
TNC vs IO BO3 第二场2.13
2021/03/10 DOTA
符合标准的js表单提交的代码
2007/09/13 Javascript
关于event.cancelBubble和event.stopPropagation()的区别介绍
2011/12/11 Javascript
Javascript面向对象编程
2012/03/18 Javascript
js判断FCKeditor内容是否为空的两种形式
2013/05/14 Javascript
jQuery 淡出一个图像到另一个图像的实现代码
2013/06/12 Javascript
js实现精美的图片跟随鼠标效果实例
2015/05/16 Javascript
JavaScript中计算网页中某个元素的位置
2015/06/10 Javascript
jQuery常用且重要方法汇总
2015/07/13 Javascript
JavaScript原生节点操作小结
2017/01/17 Javascript
进阶之初探nodeJS
2017/01/24 NodeJs
使用javascript函数编写简单银行取钱存钱流程
2018/05/26 Javascript
使用js实现将后台传入的json数据放在前台显示
2018/08/06 Javascript
微信小程序实现底部导航
2018/11/05 Javascript
js实现一个页面多个倒计时的3种方法
2019/02/25 Javascript
Element-ui中元素滚动时el-option超出元素区域的问题
2019/05/30 Javascript
jquery html添加元素/删除元素操作实例详解
2020/05/20 jQuery
[58:54]EG vs RNG 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
在Python下使用Txt2Html实现网页过滤代理的教程
2015/04/11 Python
Python 通过URL打开图片实例详解
2017/06/01 Python
机器学习python实战之手写数字识别
2017/11/01 Python
Python将图片转换为字符画的方法
2020/06/16 Python
python smtplib模块自动收发邮件功能(二)
2018/05/22 Python
django自定义非主键自增字段类型详解(auto increment field)
2020/03/30 Python
Win10用vscode打开anaconda环境中的python出错问题的解决
2020/05/25 Python
斯福泰克软件测试面试题
2015/02/16 面试题
三爱活动实施方案
2014/03/19 职场文书
排查MySQL生产环境索引没有效果
2022/04/11 MySQL