del MyClass 不会调用 object.__del__()
我有一个类,用来打开文件进行写入。在我的析构函数里,我调用了一个关闭文件的函数:
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.
而如果我在 del myobj
之前调用 myobj.close()
,就不会出现这个问题。那么,为什么 __del__()
没有被调用呢?
4 个回答
你的代码应该继承自 object
,不这样做在过去六年里被认为是过时的做法(当然有些特殊情况除外)。
你可以在这里了解 __del__
的相关信息: http://docs.python.org/reference/datamodel.html#object.del
简单来说,为什么你需要继承自 object
是因为 __del__
只有在新式类中才算是“魔法”。
如果你需要依赖于某个清理函数的调用,我强烈建议你使用其他答案中提到的上下文管理器的方法,因为那是一种可移植且可靠的解决方案。
其实,del
和__del__
是两回事。很遗憾的是,它们的名字一样,但实际上没有任何关系。在现代的说法中,__del__
这个方法应该叫做终结器,而不是析构器,这两者之间的区别很重要。
简单来说,析构器什么时候被调用是比较容易保证的,但对于__del__
什么时候会被调用,你几乎没有什么保证,甚至可能永远不会被调用。这种情况可能有很多不同的原因。
如果你想要词法作用域,可以使用with
语句。否则,直接调用myobj.close()
就可以了。del
语句只是删除引用,并不会删除对象。
我找到另一个答案(链接),它详细回答了不同的问题。很遗憾的是,那道题的被接受答案里有一些严重的错误。
编辑:正如评论者所提到的,你需要从object
继承。这是可以的,但仍然有可能__del__
永远不会被调用(你可能只是运气好)。请查看上面的链接答案。
你确定要使用 __del__
吗?因为 __del__
和垃圾回收有一些 问题。
你可以把 MyClass 改成一个 上下文管理器,这样做:
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 离开 with-block
时,myobj.__exit__
(也就是 self.__fileHandle__.close()
)会被调用。