说明
《Python 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gr99123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
在 Python 中,__del__
是一个特殊方法(也称为魔术方法或者魔法方法),用于定义对象销毁时的行为。它在对象被垃圾回收器回收之前被调用。注意,__del__
方法并不是像构造函数 __init__
一样由 Python 自动调用的,而是由解释器的垃圾回收机制触发调用的。
参数为 object.__del__(self)
,__del__
方法有一个形参 self,用于引用要销毁的对象本身。在 __del__
方法内部,你可以编写任何清理代码,例如关闭文件、释放资源等操作。
在实例将被销毁时调用。 这还被称为终结器或析构器(不适当)。 如果一个基类具有 __del__()
方法,则其所派生的类如果也有 __del__()
方法,就必须显式地调用它以确保实例基类部分的正确清除。
__del__()
方法可以 (但不推荐!) 通过创建一个该实例的新引用来推迟其销毁。这被称为对象 重生。__del__()
是否会在重生的对象将被销毁时再次被调用是由具体实现决定的 ;当前的 CPython 实现只会调用一次。
当解释器退出时不会确保为仍然存在的对象调用 __del__()
方法。
备注:del x
并不直接调用 x.__del__()
--- 前者会将 x 的引用计数减一,而后者仅会在 x 的引用计数变为零时被调用。
一个引用循环可以阻止对象的引用计数归零。 在这种情况下,循环将稍后被检测到并被 循环垃圾回收器 删除。 导致引用循环的一个常见原因是当一个异常在局部变量中被捕获。 帧的局部变量将会引用该异常,这将引用它自己的回溯信息,它会又引用在回溯中捕获的所有帧的局部变量。
由于调用 __del__()
方法时周边状况已不确定,在其执行期间发生的异常将被忽略,改为打印一个警告到 sys.stderr。特别地:
__del__()
可在任意代码被执行时启用,包括来自任意线程的代码。如果 __del__()
需要接受锁或启用其他阻塞资源,可能会发生死锁,例如该资源已被为执行 __del__()
而中断的代码所获取。
__del__()
可以在解释器关闭阶段被执行。因此,它需要访问的全局变量(包含其他模块)可能已被删除或设为 None。Python 会保证先删除模块中名称以单个下划线打头的全局变量再删除其他全局变量;如果已不存在其他对此类全局变量的引用,这有助于确保导入的模块在 __del__()
方法被调用时仍然可用。
以下是一个简单的示例:
class MyClass:
def __init__(self, name):
self.name = name
print(f"{self.name} object created")
def __del__(self):
print(f"{self.name} object deleted")
# 创建对象
obj1 = MyClass("obj1")
# obj1 object created
# 删除对象
del obj1
# obj1 object deleted
print(obj1)
# NameError: name 'obj1' is not defined
在这个示例中,MyClass 类包含了 __del__
方法。当对象被销毁时(通过 del 关键字删除对象),__del__
方法被调用并打印出相应的消息。
需要注意的是,虽然 __del__
方法可以用来进行资源的清理工作,但它的使用也可能会引发一些问题,比如不可预测的调用时间、循环引用等。因此,在大多数情况下,更好的做法是使用上下文管理器(with 语句)或者其他资源管理技术来确保资源的及时释放。
https://docs.python.org/zh-cn/3/reference/datamodel.html#object.__del__
更新时间:2024-03-03 21:03:33 标签:python 特殊方法 删除