第8.18节 Python类中内置析构方法__del__
一、 引言
基本上所有支持OOP设计的语言都支持析构方法(也称析构函数),析构方法都是在对象生命周期结束时调用,一般用来实施实例相关生命周期内访问数据的扫尾工作,包括关闭文件、释放内存、输出日志、清理数据等。
二、 析构方法语法
Python中所有类的析构方法都是特殊方法__del__,析构方法同样是一个实例方法,其语法如下:
del(self)
self就是对象自身,所有实例方法都有该参数,真正调用时无需传递。
析构方法没有返回值要求。
析构方法语法很简单,没有需要过多解释的地方。
三、 析构方法的使用
- 析构方法比较特殊,这是因为它是Python中定义的特殊方法,在对象销毁时自动执行,但在object类内却没有该方法,在自定义类定义时,并没有要求一定要自己定义析构方法,因此在自定义类及其自定义父类中没有定义__del__析构方法时,该类就没有析构方法;
- 如果子类定义了析构方法,其派生的父类也定义了析构方法,则在子类的析构方法中必须调用父类的析构方法;
- 当程序不再需要一个 Python 对象时,系统必须把该对象所占用的内存空间释放出来,这个过程被称为垃圾回收(GC,Garbage Collector),Python 会自动回收所有对象所占用的内存空间,开发者无须关心对象垃圾回收的过程。垃圾回收会自动触发对析构方法的调用;
- 使用del删除实例对象时,并不一定会触发析构方法的调用
1>Python中可能存在多个实例ID相同的情况,如实例a通过赋值语句赋值给b时,此时a与b的ID相同,就认为该ID对象上增加了一个引用;如果一个对象有多个变量引用它,那么 del 其中一个变量是不会回收该对象的。这个销毁的动作还是需要等待对象引用没有了以后才能够完成。
2>Python 采用自动引用计数(ARC:Automatic Reference Counting)方式来判断对象是否需要被回收,当程序中有一个变量引用该对象时,Python 会自动设置该对象引用计数为1;当程序中每增加一个变量引用该 Python 对象(如赋值)时,Python 会自动对该对象引用计数加1,反之如果每减少一个(如del 变量)变量的引用,该对象引用计数就减一,当对象的引用计数变成 0,则说明不再有变量引用该对象,Python 就会回收该对象,此时才会调用析构方法;
3>大部分时候,Python 的 ARC 都能准确、高效地回收系统中的每个对象。但如果系统中出现循环引用的情况,如两个对象下的属性相互指向对方(如双向链表),但两个对象都没有单独的变量引用它们,此时两个对象的引用计数并不是0,而都是1,但实际上程序已经不再有变量引用它们,此时 Python 的垃圾回收器就可能没那么快,要等专门的循环垃圾回收器(Cyclic Garbage Collector)来检测并回收这种引用循环。 - 由于调用 del() 方法时周边状况已不确定,如部分关联对象已经回收、部分模块删除了等,因此Python对在__del__() 方法执行期间发生的异常将被忽略,改为打印一个警告到 sys.stderr;
- 老猿验证在交互模式执行del实例变量时,哪怕对象没有引用了,Python也不一定马上执行垃圾回收和__del__方法,会出现比较复杂的情况,可能在del语句执行一段时间后执行其他语句时突然释放。对此老猿不展开多说,为此老猿下面的代码是通过文件方式执行的。
四、 例子 - 案例说明
本节定义Vehicle类和Car类,后者是从前者派生的。将在定义实例后,将实例赋值给另一个变量,然后使用del删除变量,看看是否能触发析构方法。 - 源代码
class Vehicle():
def __init__(self,wheelcount,power):
self.wheelcount = wheelcount
self.power = power
print("In Vehicle init,objectid = {:#016X}".format(id(self)))
def __del__(self):
print("in Vehicle __del__,delete objectid = {:#016X}".format(id(self)))
print("Vehicle deleted")
class Car(Vehicle):
def __init__(self, power,oilcostper100km):
print("In Car init,objectid = {:#016X}".format(id(self)))
self.oilcostper100km = oilcostper100km
super().__init__(4, power)
def __del__(self):
print("in Car __del__,delete objectid = {:#016X}".format(id(self)))
super().__del__()
print("Car deleted")
print("execut Car('汽油发动机',10)...")
car = Car('汽油发动机',10) #对象引用数为1
c=car #对象引用数为2
print("execut del car...")
del car #对象引用数为1
print("execut del c...")
del c #对象引用数为0,应该触发析构方法
print("Prog end.")
源代码截图:

执行结果截图:

案例总结
通过上述截图可以看出,在引用数为0才触发了析构方法。
最后,老猿需要强调一点,在Python中析构方法的使用要慎重,一是因为del变量不一定触发析构方法,二是因为调用 del() 方法时周边状况已不确定,三是Python有自己的垃圾回收机制执行相关资源的回收和清理,因此编程者意图在析构方法中实施的操作不一定会按照编程者的意图完整实施。
本节对Python析构方法的语法、使用以及注意事项进行了深入介绍,并举例进行了验证,请大家理解,并慎重使用!
老猿Python,跟老猿学Python!
博客地址:https://blog.csdn.net/LaoYuanPython
请大家多多支持,点赞、评论和加关注!谢谢!
第8.18节 Python类中内置析构方法__del__的更多相关文章
- 第8.9节 Python类中内置的查看直接父类的__bases__属性
终于介绍完了__init__方法和__new__方法,接下来轻松一下,本节介绍类中内置的__bases__属性. 一. 语法释义 Python 为所有类都提供了一个 bases 属性,通过该属性可以查 ...
- 第8.14节 Python类中内置方法__str__详解
一. object类内置方法__str__和函数str 类的内置方法__str__和内置函数str实际上实现的是同一功能,实际上str调用的就是__str__方法,只是调用方式不同,二者的调用语法如下 ...
- 第8.13节 Python类中内置方法__repr__详解
当我们在交互环境下输入对象时会直接显示对象的信息,交互环境下输入print(对象)或代码中print(对象)也会输出对象的信息,这些输出信息与两个内置方法:__str__方法和__repr__方法有关 ...
- python - 类的内置 attr 方法
类的内置 attr 方法 #类的内置 attr 方法: # __getattr__ # __setattr__ # __delattr__ # __getattr__ #到调用一个类不存在数参数时,将 ...
- python -- 类中--内置方法
isinstance 和 issubclass isinstance(obj,b) 检查是否obj是否是类b的对象 class A(object):pass class B(A):pass b=B ...
- 第7.17节 Python类中的静态方法装饰器staticmethod 定义的静态方法深入剖析
第7.17节 Python类中的静态方法装饰器staticmethod 定义的静态方法深入剖析 静态方法也是通过类定义的一种方法,一般将不需要访问类属性但是类需要具有的一些能力可以静态方法提供. 一 ...
- 第7.14节 Python类中的实例方法详析
第7.14节 Python类中的实例方法详析 一. 实例方法的定义 在本章前面章节已经介绍了类的实例方法,实例方法的定义有三种方式: 1. 类体中定义实例方法 第一种方式很简单,就是在类体 ...
- 第8.6节 Python类中的__new__方法深入剖析:调用父类__new__方法参数的困惑
上节<第8.5节 Python类中的__new__方法和构造方法__init__关系深入剖析:执行顺序及参数关系案例详解>通过案例详细分析了两个方法的执行顺序,不知大家是否注意到了,在上述 ...
- 第8.12节 Python类中使用__dict__定义实例变量和方法
上节介绍了使用实例的__dict__查看实例的自定义属性,其实还可以直接使用__dict__定义实例变量和实例方法. 一. 使用__dict__定义实例变量 语法: 对象名. dict[属性名] = ...
随机推荐
- C++实现管理系统
概述 系统中需要实现的功能如下: 添加联系人:向通讯录中添加新人,信息包括(姓名.性别.年龄.联系电话.家庭住址)最多记录1000人 显示联系人:显示通讯录中所有的联系人信息 删除联系人:按照姓名进行 ...
- 释放至强平台 AI 加速潜能 汇医慧影打造全周期 AI 医学影像解决方案
基于英特尔架构实现软硬协同加速,显著提升新冠肺炎.乳腺癌等疾病的检测和筛查效率,并帮助医疗科研平台预防"维度灾难"问题 <PAGE 1 LEFT COLUMN: CUSTOM ...
- MySQL中EXPLAIN结果的参数详解
explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了.如: mysql& ...
- 还不懂Docker?一个故事安排的明明白白!
程序员受苦久矣 多年前的一个夜晚,风雨大作,一个名叫Docker的年轻人来到Linux帝国拜见帝国的长老. "Linux长老,天下程序员苦于应用部署久矣,我要改变这一现状,希望长老你能帮帮我 ...
- linux域名解析引起登陆慢
linux域名解析引起登陆慢的问题在于,ssh去登录这个台机器的时候,本机会去通过域名解析获取登录主机的主机名,所有一旦域名解析是无效的,需要等待较长时间 解决办法一: 将域名解析指到127.0.0. ...
- Qiskit 安装指南
内容参考官方文档 https://qiskit.org/documentation/install.html conda create -n name_of_my_env python=3 创建虚拟环 ...
- PicGo+jsDelivr+GitHub搭建免费图床,Typora使用图床
Github配置 首先,创建一个GitHub账号 然后添加一个仓库 创建完后点头像,Setting 然后点击Developer settings 然后点击Personal access tokens ...
- PHP的命令执行漏洞学习
首先我们来了解基础 基础知识来源于:<web安全攻防>徐焱 命令执行漏洞 应用程序有时需要调用一些执行系统命令的函数,如在PHP中,使用system.exec.shell_exec.pas ...
- ci爬坑
1.row_array() 问题描述:没有数据返回NULL,直接foreach,报错
- 在FL Studio中有序地处理人声的混音轨道
关于人声处理的技巧,我们在以前也有讲到很多,当然在以后也会有新的人声处理技巧课程,这是在音乐后期制作中无法避免的一个环节,在制作许多流行音乐时都会用到,今天先为大家讲解一下在FL Studio中更有序 ...