我看到一个定义了 __del__法的类。此方法用于销毁类的实例。但是,我找不到使用此方法的位置。如何使用这种方法?像这样: obj1.del()?.
__del__
obj1.del()
如何调用 __del__方法?
__del__是 终结者。当一个对象是 垃圾收集时调用它,该对象在删除对该对象的所有引用之后的某个时刻发生。
在 简单的案子中,这可能是在你说 del x之后,或者,如果 x是一个局部变量,在函数结束之后。特别是,除非有循环引用,否则 CPython (标准 Python 实现)将立即进行垃圾收集。
del x
x
但是,这是 CPython 的 实施细节。Python 垃圾收集的唯一 需要属性是发生 之后所有引用都已被删除,因此这可能不一定发生 就在那之后和 可能根本不会发生。
更重要的是,对于 很多原因,变量可以存活很长时间,例如,传播异常或模块自省可以使变量引用计数保持大于0。此外,变量可以是 参考文献循环ー CPython 的一部分,其中大部分(但不是全部)这样的周期打开了垃圾收集,甚至只是周期性地打开。
因为不能保证执行,所以应该由 finally1将需要运行的代码放入 __del__()ーー而不是,这段代码属于 try块的 finally子句或 with语句中的上下文管理器。然而,对于 __del__有 finally2: 例如,如果一个对象 X引用 Y,并且在全局 cache(cache['X -> Y'] = Y)中保留 Y引用的一个副本,那么对于 finally0也删除缓存条目是有礼貌的。
finally
__del__()
try
with
X
Y
cache
cache['X -> Y'] = Y
如果您知道 析构函数提供了(违反上述准则)所需的清理,那么您可能需要 直接打电话,因为它作为方法没有什么特殊之处: x.__del__()。显然,只有当您知道它可以被调用两次时,才应该这样做。或者,作为最后的手段,您可以使用
x.__del__()
type(x).__del__ = my_safe_cleanup_method
__del__方法(注意拼写!)当对象最终被销毁时调用。从技术上讲(在 cPython 中) ,这是指没有更多的对象引用,即当它超出作用域时。
如果要删除对象并因此调用 __del__方法,请使用
del obj1
它将删除该对象(假设没有任何其他对它的引用)。
我建议您编写一个这样的小类
class T: def __del__(self): print "deleted"
并在 Python 解释器中进行调查,例如
>>> a = T() >>> del a deleted >>> a = T() >>> b = a >>> del b >>> del a deleted >>> def fn(): ... a = T() ... print "exiting fn" ... >>> fn() exiting fn deleted >>>
注意,jython 和 ironpython 对于删除对象和调用 __del__的确切时间有不同的规则。尽管使用 __del__被认为是不好的实践,但是由于这个原因,以及对象及其环境在被调用时可能处于未知状态的事实。也不能绝对保证 __del__会被调用——解释器可以通过各种方式退出,而无需删除所有对象。
当对象被垃圾收集时,将调用 __del__方法。但是请注意,并不一定要保证调用它。下面的代码本身不一定能做到这一点:
del obj
原因是 del只是将引用计数减1。如果其他对象有对该对象的引用,则不会调用 __del__。
del
不过,使用 __del__需要注意一些问题。一般来说,他们只是不太有用。在我看来,这更像是你想要使用一个 close 方法或者 发表声明。
看看 关于 __del__方法的 python 文档。
还有一点需要注意: 如果过度使用,__del__方法可以抑制垃圾收集。特别是,具有多个具有 __del__方法的对象的循环引用不会被垃圾收集。这是因为垃圾收集器不知道先调用哪一个。有关更多信息,请参见 气相色谱模块上的文档。
我写了另一个问题的答案,尽管这个问题更准确。
构造函数和析构函数是如何工作的?
这是一个有点固执己见的答案。
不要用 __del__。这不是 C + + ,也不是为析构函数构建的语言。在 Python 3.x 中,__del__方法确实应该消失,尽管我确信有人会找到一个有意义的用例。如果您需要使用 __del__,请注意每个 http://docs.python.org/reference/datamodel.html的基本限制:
del object
__new__
__init__
但另一方面:
以及我个人不喜欢 __del__功能的原因。
因此,找到不使用 __del__的理由。
如前所述,__del__功能有些不可靠。在它看起来有用的情况下,考虑使用 __enter__和 __exit__方法代替。这将提供类似于用于访问文件的 with open() as f: pass语法的行为。当进入 with的作用域时自动调用 __enter__,而当退出作用域时自动调用 __exit__。有关详细信息,请参阅 这个问题。
__enter__
__exit__
with open() as f: pass