15

是否有任何障碍妨碍weakref做所有__del__所做的一切,但有更强的保证(例如,finalize保证在解释器退出之前进行调用,并且调用顺序已定义良好等)?`weakref`回调可以代替`__del__`吗?

看来,在遥远的过去it was thoughtweakref最终将导致从语言中删除__del__

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

似乎有few use cases for __del__,我知道所有的人似乎至少工作(通常好得多)与weakref回调或weakref.finalize

更新:

随着PEP 442显着提高的__del__的行为,并与weakref由@gz和@ user2357112提到的关切,我想知道如果语言通常是朝着使__del__更可靠的移动,或对使用weakref而不是__del__或两者。

+1

*“是什么阻止了这种情况的发生?”*这是一个很*很少能够回答的问题。我建议你在'python-list'上发布这个文件,希望得到一些核心开发者的关注。 –

+2

Python的weakref支持非常糟糕,所以你不能将weakrefs引用到很多你想weakref的对象类型。这对你自己编写的类型通常无关紧要,但是如果你的类型像'tuple'子类一样,你不能弱化它。 – user2357112

+1

此外,weakref回调无法访问指示对象,因此需要更仔细的设计。 – user2357112

回答

3

有一个有点务实的原因__del__仍然存在。几个重要的改进weakref,包括finalize,分别是new in Python 3.4。所以,用更好的弱点代替__del__就错过了用py3k改变语言的窗口。

我想大多数使用可以由基weakref功能所取代,但我这个观察理查德奥德柯克在issue 15528袭击,其中提出并实现finalize

[Weakref回调]低级别,并正确使用它们需要一些头部划痕。必须找到某处存储weakref,直到指示对象死亡,并且不会意外地保留指示对象。然后必须确保回调释放weakref(不留任何剩余的ref-cycles)。

当它是一个选项,使用__del__方法是少得多的麻烦。

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

1

问题的答案是真的依赖于使用情况和也建议你考虑到不同的Python解释器的实现没有相同的GC行为CPython的。

PyPy特别不呼叫__del__作为-即将作为对象是del -eleted或超出范围,但“一段时间后”。因此,依赖于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或超出范围将最终清除对象引用,这取决于解释器的实现,但是应立即执行的事情最好不要依赖于该行为。

相关问题