首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >del MyClass不调用object.__del__()

del MyClass不调用object.__del__()
EN

Stack Overflow用户
提问于 2012-01-18 17:34:56
回答 4查看 6.3K关注 0票数 6

我有一个类,可以打开一个文件进行写入。在我的析构函数中,我调用了关闭文件的函数:

代码语言:javascript
复制
class MyClass:
    def __del__(self):
        self.close()

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

但是当我使用如下代码删除对象时:

代码语言:javascript
复制
myobj = MyClass()
myobj.open()
del myobj

如果我试图重新实例化对象,我得到一个值错误:

代码语言:javascript
复制
ValueError: The file 'filename' is already opened.  Please close it before reopening in write mode.

但是,如果我在del myobj之前调用myobj.close(),我就不会遇到这个问题。那么为什么__del__()没有被调用呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-01-18 17:49:51

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

您可以将MyClass设置为context manager

代码语言:javascript
复制
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

代码语言:javascript
复制
with MyClass() as myobj:
    ...

当Python离开with-block时,myobj.__exit__ (以及self.__fileHandle__.close())将被调用。

票数 8
EN

Stack Overflow用户

发布于 2012-01-18 17:49:33

这不是del所做的。不幸的是,__del__del同名,因为它们彼此没有关系。在现代术语中,__del__方法将被称为终结器,而不是析构函数,区别很重要。

简短的区别是,很容易保证何时调用析构函数,但您几乎不能保证何时调用__del__,而且可能永远不会调用它。有许多不同的情况可以导致这种情况。

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

我找到了另一个问题的答案(link),它更详细地回答了这个问题。不幸的是,对这个问题的公认答案包含了严重的错误。

编辑:正如评论员所说,你需要从object继承。这很好,但仍然有可能永远不会调用__del__ (您可能会走运)。请参阅上面的链接答案。

票数 8
EN

Stack Overflow用户

发布于 2012-01-18 17:51:14

您的代码应该继承自object -至少六年来,不这样做已经被认为是过时的(除非在特殊情况下)。

你可以在这里阅读关于__del__的文章:http://docs.python.org/reference/datamodel.html#object.

简而言之,为什么需要继承object的原因是,__del__只对新样式的类具有“魔力”。

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8907905

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档