[Python-3000] PEP: Eliminate __del__

Guido van Rossum guido at python.org
Fri May 4 20:09:42 CEST 2007


On 5/4/07, Steven Bethard <steven.bethard at gmail.com> wrote:
> 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.::

Oh, you mean 'self' as passed to the callback is not the instance?
That kills the whole idea (since the typical __del__ calls
self.flush() or self.close()).

> >>> 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

If it really has to be done this way, I think the whole PEP is doomed.

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-3000 mailing list