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 相关文章推荐
python学习教程之Numpy和Pandas的使用
Sep 11 Python
python实现简易版计算器
Jun 22 Python
基于Python socket的端口扫描程序实例代码
Feb 09 Python
django开发post接口简单案例,获取参数值的方法
Dec 11 Python
Python中的 enum 模块源码详析
Jan 09 Python
弄懂这56个Python使用技巧(轻松掌握Python高效开发)
Sep 18 Python
Django框架获取form表单数据方式总结
Apr 22 Python
Python3 用什么IDE开发工具比较好
Nov 28 Python
matplotlib 使用 plt.savefig() 输出图片去除旁边的空白区域
Jan 05 Python
教你使用Pandas直接核算Excel中快递费用
May 12 Python
Python天气语音播报小助手
Sep 25 Python
python中tkinter复选框使用操作
Nov 11 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中0,null,empty,空,false,字符串关系的详细介绍
2013/06/20 PHP
两种php去除二维数组的重复项方法
2015/11/04 PHP
swoole和websocket简单聊天室开发
2017/11/18 PHP
PHP Swoole异步读取、写入文件操作示例
2019/10/24 PHP
javascript 模拟点击广告
2010/01/02 Javascript
javascript Firefox与IE 替换节点的方法
2010/02/24 Javascript
基于jQuery的仿flash的广告轮播代码
2010/11/04 Javascript
JS控件的生命周期介绍
2012/10/22 Javascript
node.js中的fs.link方法使用说明
2014/12/15 Javascript
JS实现模拟风力的雪花飘落效果
2015/05/13 Javascript
zepto与jquery的区别及zepto的不同使用8条小结
2016/07/28 Javascript
AngularJS 过滤与排序详解及实例代码
2016/09/14 Javascript
Three.js加载外部模型的教程详解
2017/11/10 Javascript
VuePress 快速踩坑小结
2019/02/14 Javascript
vue 实现用户登录方式的切换功能
2020/04/14 Javascript
nuxt 页面路由配置,主页轮播组件开发操作
2020/11/05 Javascript
[02:53]DOTA2英雄昆卡基础教程
2013/11/25 DOTA
Python实现FTP上传文件或文件夹实例(递归)
2017/01/16 Python
Python实现图片尺寸缩放脚本
2018/03/10 Python
对Python 窗体(tkinter)文本编辑器(Text)详解
2018/10/11 Python
python已协程方式处理任务实现过程
2019/12/27 Python
Python生成器常见问题及解决方案
2020/03/21 Python
python Tornado框架的使用示例
2020/10/19 Python
python openpyxl模块的使用详解
2021/02/25 Python
Python爬取酷狗MP3音频的步骤
2021/02/26 Python
css3 伪元素和伪类选择器详解
2014/09/04 HTML / CSS
北京天润融通.net面试题笔试题
2012/02/20 面试题
什么是servlet链?
2014/07/13 面试题
财务会计专业个人求职信范本
2014/01/08 职场文书
《藤野先生》教学反思
2014/02/19 职场文书
大学毕业生个人自荐书
2014/07/02 职场文书
公司委托书格式范文
2014/10/09 职场文书
2015年法律事务部工作总结
2015/07/27 职场文书
新农村建设指导员工作总结
2015/08/13 职场文书
2019年最新版见习人员管理制度!
2019/07/08 职场文书
Python道路车道线检测的实现
2021/06/27 Python