Python __del__() 方法

Python __del__() 语法

__del__() 是 Python 的一个特殊方法(又称 “魔法方法” 或 “双下划线方法”), 它在对象被垃圾回收前自动调用,用于执行清理工作。

语法:

class MyObject:
    def __del__(self):
        # 执行清理操作
        # 释放资源等

说明:

__del__() 方法不接收任何参数,除了 self(实例本身)。它不应返回任何值。

注意:

  • __del__() 方法的调用时机是不确定的,Python 的垃圾回收机制决定了何时回收对象。
  • 强烈建议避免在 __del__() 中处理复杂的逻辑或可能引发异常的操作,因为异常在析构器中可能会导致程序崩溃或不可预测的行为。

Python __del__() 摘要

属于 Python 魔法方法
使用频率
官方文档 查看

Python __del__() 示例

接下来,我们通过几个简单的例子来讲解一下 Python __del__() 方法是如何使用的。

示例 1:__del__() 的调用时机

import gc

class MyResource:
    def __init__(self, name):
        self.name = name
        print(f'“{self.name}” 已创建')

    def __del__(self):
        print(f'“{self.name}” 被销毁')

# 创建实例
res1 = MyResource('文件A')
res2 = MyResource('连接B')

# 显式删除引用(引用计数减 1)
del res1

# 此时 res2 仍然存在,当程序结束或所有引用消失时才会被销毁
print('程序即将结束')

# 强制执行垃圾回收(不推荐在生产代码中频繁使用)
gc.collect()
print('强制垃圾回收完成')

运行结果如下。

“文件A” 已创建
“连接B” 已创建
“文件A” 被销毁
程序即将结束
强制垃圾回收完成
“连接B” 被销毁

分析:

当 del res1 执行时,res1 对象的引用计数变为 0(假设没有其他引用),其 __del__() 方法会被立即调用。对于 res2 来说,在程序正常结束时(或者当垃圾回收器认为它不再被需要时),它的 __del__() 方法才会被调用。

从这个例子也可以看出,__del__() 的调用时机是不确定的,不像 __init__() 那样严格绑定到对象创建。

示例 2:__del__() 与循环引用

class Node:
    def __init__(self, value):
        self.value = value
        self.next = None
        self.prev = None
        print(f'节点 “{self.value}” 被创建')

    def __del__(self):
        print(f'节点 “{self.value}” 被销毁')

def create_circular_reference():
    a = Node('A')
    b = Node('B')
    a.next = b
    b.prev = a
    print('创建循环引用:A <-> B')
    return a, b

# 创建循环引用
nodeA, nodeB = create_circular_reference()

# 删除外部引用
del nodeA
del nodeB
print('外部引用已删除')

# 此时,NodeA 和 NodeB 的 __del__() 可能不会立即被调用,因为它们之间存在循环引用。
# Python 的分代垃圾回收器最终会处理它们,但时机不确定。
import gc
print('强制垃圾回收开始')
gc.collect()
print('强制垃圾回收完成')

运行结果如下。

节点 “A” 被创建
节点 “B” 被创建
创建循环引用:A <-> B
外部引用已删除
强制垃圾回收开始
节点 “A” 被销毁
节点 “B” 被销毁
强制垃圾回收完成

分析:

即使删除了 nodeA 和 nodeB 的外部引用,如果它们之间形成循环引用,它们的引用计数可能不会降到 0。在这种情况下,__del__() 便不会立即被触发。

Python 的分代垃圾回收器会周期性地检测并回收这些循环引用的对象,因此 __del__() 最终仍会被调用,但其时机变得更加不可预测。

上一篇: __new__()

下一篇: __str__()

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号