`weakref` 回调可以替代 `__del__` 吗?

Can `weakref` callbacks replace `__del__`?

是否有任何障碍阻止 weakref 执行 __del__ 所做的所有事情,但有更强的保证(例如,finalize 保证调用将在解释器退出之前进行, 调用顺序明确等)?

似乎在遥远的过去 it was thought weakref 最终会导致从语言中删除 __del__

是什么阻止了这种情况的发生?

似乎有 ,而且我所知道的所有那些似乎至少与 weakref 回调或 weakref.finalize 一样有效(通常更好) .

更新:

随着 PEP 442 显着改善 __del__ 的行为,以及@gz 和 @user2357112 提到的 weakref 的问题,我想知道该语言是否总体上朝着使 __del__ 更可靠,或使用 weakref 而不是 __del__,或两者兼而有之。

__del__ 仍然存在有一些务实的原因。 weakref 多项重大改进,包括 finalize,是 new in Python 3.4。因此,用更好的 weakrefs 替换 __del__ 错过了 window 对 py3k 的语言中断更改。

我认为大多数用途 可以 被基本的 weakref 功能取代,但我对 Richard Oudkerk 在 issue 15528 提出并实施 finalize:

[Weakref callbacks] are low level, and working out how to use them correctly requires a bit of head scratching. One must find somewhere to store the weakref till after the referent is dead, and without accidentally keeping the referent alive. Then one must ensure that the callback frees the weakref (without leaving any remnant ref-cycles).

When it is an option, using a __del__ method is far less hassle.

无论如何,也许在考虑Python 4 时再提出这个问题? ;)

问题的答案确实取决于用例并且还建议您考虑不同的 Python 解释器实现不具有与 C 相同的 GC 行为Python.

PyPy 特别是 不会 调用 __del__ 一旦对象被 del 删除或超出范围但 'some time later'.因此,依赖于 CPython 的 __del__ 行为的代码将在 PyPy 和其他替代解释器上中断。

我建议使用 __enter____exit__ 以及 with 关键字。例如

from __future__ import print_function

class MyClass(object):

    def __enter__(self):
        print("Entering")

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting")

# 'with MyClass()' can be used but want to show that
# code in exit is executed regardless of object
# life time
obj = MyClass()
with obj:
    print("Stuff happening in between")

结果是:

Entering
Stuff happening in between
Exiting

上述语句顺序是有保证的,不依赖于 GC 行为。

with 块中的代码完成后应该做的事情可以放在 __exit__ 中,例如通常会放在析构函数中的事情 - 清除文件句柄,释放锁等等。

对象上的后续 del,或者它超出范围,最终将清除对象引用,这同样取决于解释器的实现,但是应该立即完成的事情最好不要依赖于该行为。