[Python-3000] Removing __del__
Nick Coghlan
ncoghlan at gmail.com
Wed Sep 20 13:18:58 CEST 2006
Michael Chermside wrote:
> The following comments got me thinking:
>
> Raymond:
>> Statistics incontrovertibly prove that people who habitually
>> avoid __del__ lead happier lives and spend fewer hours in therapy ;-)
>
> Adam Olsen:
>> I agree here. I think an executor approach is much better; kill the
>> object, then make a weakref callback do any further cleanups using
>> copies it made in advance.
>
> What'cha think folks? I'd love to hear an opinion from someone who
> is a current user of __del__ -- I'm not.
How about an API change and a tweak to type.__call__, rather than complete
removal?
I've re-used __del__ as the method name below, but a different name would
obviously work too.
1. __del__ would become an automatic static method (like __new__)
2. Make an addition to the end of type.__call__ along the lines of (stealing
from Jean-Paul's example):
# sys.finalizers would just be a new global set in the sys module
# that keeps the weakrefs alive until they are needed
# In definition of type.__call__, after invoking __init__
if hasattr(cls, '__del__'):
finalizer = cls.__del__
if hasattr(self, '__del_arg__'):
finalizer_arg = self.__del_arg__
else:
# Create a class with the same instance attributes
# as the original
class attr_holder(object):
pass
finalizer_arg = attr_holder()
finalizer_arg.__dict__ = self.__dict__
def call_finalizer(ref):
sys.finalizers.remove(ref)
finalizer(finalizer_arg)
sys.finalizers.add(weakref.ref(self, call_finalizer))
3. The __init__ method then simply needs to make sure that the right argument
is passed to __del__. For example, if the object holds a reference to a file
that needs to be closed when the object goes away:
class CloseFileOnDel(object):
def __init__(self, fname):
self.f = self.__del_arg__ = open(fname)
def __del__(f):
f.close()
Alternatively, the class could rely on the pseudo-self that is passed if
__del_arg__ isn't defined:
class CloseFileOnDel(object):
def __init__(self, fname):
self.f = open(fname)
def __del__(self_attrs):
self_attrs.f.close()
The only way for __del__ to receive a reference to self is if the finalizer
argument had a reference to it - but that would mean the object itself was not
collectable, so __del__ wouldn't be called in the first place.
That all seems too simple, though. Since we're talking about gc and that's
never simple, there has to be something wrong with the idea :)
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
http://www.boredomandlaziness.org
More information about the Python-3000
mailing list