失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Python面向对象程序设计中对象析构方法的调用时机

Python面向对象程序设计中对象析构方法的调用时机

时间:2020-04-17 04:02:41

相关推荐

Python面向对象程序设计中对象析构方法的调用时机

开学第一课:一定不要这样问老师Python问题

中国大学MOOC“Python程序设计基础”第6次开课时间

董付国老师Python系列教材推荐与选用参考

=============

版权声明:由于公众号后台规则问题,本文暂时无法设置原创标记,但仍属原创内容,微信公众号“Python小屋”坚持只发原创技术文章。

=============

推荐教材:

《Python程序设计(第3版)》,(ISBN:978-7-302-55083-9),董付国,清华大学出版社,6月第1次印刷,3月第12次印刷,山东省一流本科课程“Python应用开发”配套教材,清华大学出版社、度畅销图书(本书第二版为、度畅销图书)

京东购买链接:/12668739.html

天猫、当当、京东均有销售,可以选择自己常用平台搜索“董付国 第3版”找到本书。

配套资源:教学大纲(基于工程教育专业认证,含课程思政)、电子教案、微课视频、PPT课件、例题源码、习题答案、在线练习系统。

适用专业:计算机、网络工程、软件工程以及相关专业。

适用学时:>=64

页数:381

定价:59.8

微课视频:124个

教学大纲:《Python程序设计(第3版)》配套教学大纲

习题答案:《Python程序设计(第3版)》课后习题答案

====================

众所周知,从面向对象程序设计角度来讲,在Python语言中,不管类的名字是什么,构造方法的名字统一为__init__(),在创建对象时自动调用,用来对数据成员进行初始化;析构方法的名字统一为__del__(),用来释放对象占用的内存空间,在删除对象时自动调用。

创建对象的时机是很显然的,但对象被删除的时机并不像表面看上去那么简单。

为了演示和解释这个问题,我们编写下面的代码并在IDLE中运行:

从上面的运行结果来看,只有对象的构造方法被调用了,并没有调用析构方法。

但是在命令提示符环境执行这个程序时,析构方法又被调用了,在PyCharm或其他类似的开发环境中运行程序时也会得到下面的结果。

原因在哪里呢?

在命令提示符环境、PyCharm或类似环境中,是以独立进程的方式运行程序的,程序运行完的适合进程也就结束了,这时候会释放进程中所有资源,包括自己创建的所有对象,所以析构方法被调用。但在IDLE环境中,IDLE为主线程,自己的程序运行结束后IDLE主线程尚未结束,创建的对象不会自动删除,除非自己显式使用del关键字删除对象。

为了验证这个问题,在上面代码最后增加删除对象的代码,在IDLE环境中也会自动调用析构方法。

既然用到了del,我们就顺便来解释一下这个关键字的真正作用:删除变量,并解除变量与值之间的引用关系,值的引用次数减1。

在Python中,变量不直接存储值,而是存储值的引用或者内存地址,列表、元组、字典、集合、字符串等容器类对象中的元素也是如此。variable = value这样的语句并不是把value赋值给variable,而是使得variable引用value的值,也可以理解为在存放value值的内存空间贴上标签variable。

例如,x = 3这样的语句执行过程为:在内存中查找存放3的位置,在该内存上贴上标签x。当再执行x = 5语句时,把标签x从存放3的内存上撕下来然后贴到存放5的内存空间上。这也是Python中变量类型可以任意改变的原因。

如果value不是字面值而是另一个变量,那么variable = value语句的作用是使得variable具有和value相同的引用,或者说使得variable和value引用同一个内存空间,或者说给同一个内存空间贴了两个标签,此时两个变量的identity相同,使用is测试两个变量时得到True。当然,同一个内存空间可以贴任意多个标签,也就是可以使得任意多个变量引用同一个内存空间。

Python采用的是基于值的内存管理模式,在同一个程序中或交互模式下同一条语句中相同的值在内存中只保留一份,详见:Python基于值的内存管理真相。在解释器内部为每个值记录了一个引用次数,也就是当前有多少个变量在引用这个值,或者说这个对象的内存空间上被贴了多少个标签。可以使用标准库sys中的函数getrefcount()查看一个对象的当前引用次数。

当我们使用关键字del删除一个变量时,同时会解除这个变量与值之间的引用关系,从相应的内存空间上撕掉一个标签,值的引用次数减1。当引用次数变为0时,Python的垃圾回收机制就会从内存中删除这个值,回收相应的内存空间。所以,当多个变量引用同一个对象时,使用del删除其中部分变量时,并不会调用对象的析构方法。

只有当引用同一个对象的所有变量都删除之后,对象的引用次数变为0时,才会真正删除对象、调用析构方法、释放内存空间。

另外,除非使用关键字global进行声明,在函数中创建的对象均为局部变量,函数执行结束后操作系统会回收为该函数分配的栈帧,该函数中创建的所有局部变量都会被释放(不需要显式使用del关键字删除),自然也就会调用对象的析构方法。改写上面的代码如下,并在IDLE环境中运行,其他环境均会得到同样的结果。

建议:对于需要长时间运行的程序,尤其是服务端程序,使用关键字del显式删除不再使用的变量,可以及时释放资源,减轻服务器压力。

温馨提示:

关注微信公众号“Python小屋”,在公众号后台发送消息“大事记”可以查看董付国老师与Python有关的重要事件;发送消息“教材”可以查看董付国老师出版的Python系列教材(累计印刷超过150次)的适用专业详情;发送消息“历史文章”可以查看董付国老师推送的超过1000篇原创技术文章;发送消息“会议”可以查看近期董付国老师的培训安排;发送消息“微课”可以查看董付国老师免费分享的超过600节Python微课视频;发送消息“课件”可以查看董付国老师免费分享的Python教学资源;发送消息“小屋刷题”可以下载“Python小屋刷题神器”,免费练习2086道客观题和471道编程题,题库持续更新;发送消息“编程比赛”了解Python小屋编程大赛详情。

如果觉得《Python面向对象程序设计中对象析构方法的调用时机》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。