Is there any obstacle that prevents weakref
from doing everything that __del__
does but with much stronger guarantees (e.g., finalize
guarantees that the call will be made before the interpreter exits, and the order of calls is well-defined, etc.)?
It seems that in the distant past it was thought that weakref
would eventually lead to the removal of __del__
from the language.
What prevented this from happening?
There seems to be few use cases for __del__
, and all the ones I'm aware of seem to work at least as well (and usually much better) with weakref
callbacks or weakref.finalize
.
Update:
With PEP 442 dramatically improving the behavior of __del__
, and the concerns with weakref
mentioned by @gz and @user2357112, I'm wondering if the language is generally moving towards making __del__
more reliable, or towards using weakref
instead of __del__
, or both.
There's a somewhat pragmatic reason
__del__
is still around. Several signficantweakref
improvements, includingfinalize
, were new in Python 3.4. So, replacing__del__
with better weakrefs missed the window for language breaking changes with py3k.I think most uses can be replaced by the base weakref functionality, but I'm struck by this observation from Richard Oudkerk in issue 15528 where proposed and implemented
finalize
:Anyway, perhaps the question should be brought up again when Python 4 is being considered? ;)
Answer to the question is really depends on the use case and would also suggest you consider that different Python interpreter implementations do not have the same GC behaviour as CPython.
PyPy in particular does not call
__del__
as-soon-as an object isdel
-eleted or goes out of scope but 'some time later'. So code that relies on CPython's__del__
behaviour will break on PyPy, and other alternative interpreters.What I would recommend is to make use of
__enter__
and__exit__
along with thewith
keyword. For exampleResult is:
The above order of statements is guaranteed and does not depend on GC behaviour.
Things that should be done as soon as the code in the
with
block completes can go in__exit__
, such as things that would normally be put in a destructor - clearing file handles, releasing locks and so on.A subsequent
del
on the object, or it going out of scope, will clear the object reference eventually, again depending on interpreter implementation, but things that should be done immediately best not rely on that behaviour.