我需要在实例被删除时进行对象清理,但不在退出时。实例可以自我删除吗?

0 投票
2 回答
1509 浏览
提问于 2025-04-16 03:15

我想在运行时删除一个实例时做一些清理工作,但不想在程序退出时进行的垃圾回收时做这些清理。

在下面的例子中,当 c 被删除时,会有一个文件被删除,这正是我想要的;但是,当程序退出时,这个文件也会被删除,这不是我想要的。

class C:
  def __del__(self):
    os.remove(self.filename)

c=C()
del c

我可以把运行时实例的删除和一段代码关联起来,但在 Python 退出时不执行那段代码吗?

谢谢。

2 个回答

1

你想做的事情在Python中不是很常见(我觉得这可能不太可能实现)。在程序运行时删除实例通常是不必要的。

你可以在运行时用自己的函数来代替 del

def rem(object):
    object.__remove()

class C:
    def __remove(self):
        os.remove(self.filename)

c=C()
rem(c)

或者你可以把删除功能作为实例的方法来实现(这样更符合Python的风格!):

class C:
    def remove(self):
        os.remove(self.filename)

c=C()
c.remove()

或者你可以在程序结束时销毁删除处理器:

class C:
    instances = []

    def __init__(self):
        C.instances.append(self)

    def __del__(self):
        C.instances.remove(self)
        os.remove(self.filename)

c = C()
del c

# ... do something ...

for c in C.instances:
    del c.__del__
4

CPython 使用引用计数的方式来管理内存,只有在特定情况下才会运行一个完整的垃圾回收(GC),这个垃圾回收可以处理循环引用。比如,当你执行 c = C(); del c 时,新的 C 对象会立即被垃圾回收处理。至于 __del__ 方法和解释器退出时的情况,文档中提到

并不能保证在解释器退出时,仍然存在的对象的 __del__() 方法会被调用。

不过,这种情况似乎很难确定。此外(虽然这在实际中关系不大),其他实现,比如 Jython 和 IronPython,并不使用引用计数,这意味着对象的销毁和清理就不那么可预测了(理论上,在 .NET 中可能根本不会发生)。

总之,这个要求(只有在正常的垃圾回收时才执行 __del__,而不是在解释器退出时)听起来有点奇怪。你能详细说明一下为什么需要关注这个问题吗?

你可能会想要使用一个 上下文管理器

撰写回答