del MyClass不调用object .__ del __()

时间:2012-01-18 09:34:56

标签: python destructor

我有一个打开文件进行写作的课程。在我的析构函数中,我调用关闭文件的函数:

class MyClass:
    def __del__(self):
        self.close()

    def close(self):
        if self.__fileHandle__ is not None:
                self.__fileHandle__.close()

但当我用以下代码删除对象时:

myobj = MyClass()
myobj.open()
del myobj

如果我尝试重新实例化该对象,则会出现值错误:

ValueError: The file 'filename' is already opened.  Please close it before reopening in write mode.

如果我在myobj.close()之前致电del myobj,我就不会遇到这个问题。那么为什么__del__()没有被召唤?

4 个答案:

答案 0 :(得分:8)

这不是del所做的。遗憾的是__del__del具有相同的名称,因为它们彼此无关。在现代术语中,__del__方法将被称为终结器,而不是析构函数,差异很重要。

简单的区别在于,在调用析构函数时很容易保证,但是很少有人保证何时调用__del__并且永远不会被调用。有许多不同的情况可以导致这种情况。

如果您想要词法作用域,请使用with语句。否则,请直接致电myobj.close()del语句只删除引用,而不删除对象。

我找到了另一个答案(link)来回答更详细的问题。遗憾的是,对该问题的接受答案包含了令人震惊的错误。

修改:评论员指出,您需要继承object。这很好,但仍然可能永远不会调用__del__(你可能会变得幸运)。请参阅上面的链接答案。

答案 1 :(得分:8)

您确定要使用__del__吗?有issues __del__和垃圾收集。

您可以将MyClass改为context manager

class MyClass(object):
    def __enter__(self):
        return self
    def __exit__(self,ext_type,exc_value,traceback):
        if self.__fileHandle__ is not None:
                self.__fileHandle__.close()

通过这样做,您可以像这样使用MyClass

with MyClass() as myobj:
    ...
当Python离开myobj.__exit__时,将调用

self.__fileHandle__.close()(以及with-block)。

答案 2 :(得分:2)

您的代码应该继承自object - 不这样做已被视为已过期(特殊情况除外)至少六年。

您可以在此处阅读__del__http://docs.python.org/reference/datamodel.html#object.del

您需要从object继承的简短版本是__del__在新式课程中只是“神奇”。

如果您需要依赖于调用终结器,我强烈建议您使用其他答案中建议的上下文管理器方法,因为这是一种可移植的强大解决方案。

答案 3 :(得分:0)

也许其他东西正在引用它,这就是为什么__del__没有被调用的原因。

考虑以下代码:

#!/usr/bin/env python

import time

class NiceClass():
    def __init__(self, num):
        print "Make %i" % num
        self.num = num
    def __del__(self):
        print "Unmake %i" % self.num

x = NiceClass(1)
y = NiceClass(2)
z = NiceClass(3)
lst = [x, y, z]
time.sleep(1)
del x
del y
del z
time.sleep(1)
print "Deleting the list."
del lst
time.sleep(1)

在我们删除引用它们的列表之前,它不会调用__del__NiceClass个实例。

与C ++不同,__del__没有被无条件地调用以按需销毁对象。 GC使事情变得更加艰难。以下是一些信息:http://arctrix.com/nas/python/gc/