[Python-3000] PEP: Eliminate __del__

Steven Bethard steven.bethard at gmail.com
Fri May 4 20:02:45 CEST 2007


On 5/4/07, Guido van Rossum <guido at python.org> wrote:
> On 5/4/07, Raymond Hettinger <python at rcn.com> wrote:
> > An encapsulating function should be added to the weakref module
> > so that Guido's example could be written as:
> >
> > class BufferedWriter:
> >
> >   def __init__(self, raw):
> >     self.raw = raw
> >     self.buffer = ""
> >     weakref.cleanup(self, lambda s: s.raw.write(s.buffer))
>
> Or, instead of a new lambda, just use the unbound method:
>
>     weakref.cleanup(self, self.__class__.flush)
>
> Important: use the dynamic class (self.__class___), not the static
> class (BufferedWriter). The distinction matters when BufferedWriter is
> subclassed and the subclass overrides flush().
>
> Hm, a thought just occurred to me. Why not arrange for object.__new__
> to call [the moral equivalent of] weakref.cleanup(self,
> self.__class__.__del__), and get rid of the direct call to __del__
> from the destructor? (And the special-casing of objects with __del__
> in the GC module, of course.)

That seems like a good idea, though I'm still a little unclear as to
how far the AttrMap should be going to look like a real instance. As
it stands, you can only access items from the instance __dict__. That
means no methods, class attributes, etc.::

>>> import weakref
>>> def cleanup(obj, callback, _reg=[]):
...    class AttrMap(object):
...        def __init__(self, map):
...            self._map = map
...        def __getattr__(self, key):
...            return self._map[key]
...    def wrapper(wr, mp=AttrMap(obj.__dict__), callback=callback):
...        _reg.remove(wr)
...        callback(mp)
...    _reg.append(weakref.ref(obj, wrapper))
...
>>> class Object(object):
...     # note that we do this in __init__ because in __new__, the
...     # object has no references to it yet
...     def __init__(self):
...         super(Object, self).__init__()
...         if hasattr(self.__class__, '__newdel__'):
...             # note we use .im_func so that we can later pass
...             # any object as the "self" parameter
...             cleanup(self, self.__class__.__newdel__.im_func)
...
>>> class Foo(Object):
...     def flush(self):
...         print 'flushing'
...     def __newdel__(self):
...         print 'deleting'
...         self.flush()
...
>>> f = Foo()
>>> del f
deleting
Exception exceptions.KeyError: 'flush' in <function wrapper at
0x00F34630> ignored

STeVe
-- 
I'm not *in*-sane. Indeed, I am so far *out* of sane that you appear a
tiny blip on the distant coast of sanity.
        --- Bucky Katt, Get Fuzzy


More information about the Python-3000 mailing list