[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