[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