is there anybody using __del__ correctly??

Steven Bethard steven.bethard at gmail.com
Sun Aug 12 15:14:52 EDT 2007


Michele Simionato wrote:
> On Aug 10, 7:09 pm, Steven Bethard <steven.beth... at gmail.com> wrote:
>> There were also a few recipes posted during this discussion that wrap
>> weakrefs up a bit nicer so it's easier to use them in place of __del__:
>>
>> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/519635
> 
> I knew about your recipe and I thought it was clever, *very*
> clever. I have been thinking about it a bit more today and
> here is an alternative, which does not require metaclasses,
> does not require descriptors, and does not require the user to
> declare the attributes she will use in the __finalize__ method.
> Warning: it is no more tested than the test case in your recipe:
> 
> import weakref
> 
> _get = object.__getattribute__
> _set = object.__setattr__
> _del = object.__delattr__
> 
> def getinnerobj(self):
>     return _get(self, '*innerobj*')
> 
> class Impostor(object):
>     "It tries very hard to impersonate the inner object"
>     def __init__(self, obj):
>         _set(self, '*innerobj*', obj)
>     def __getattribute__(self, name):
>         return getattr(getinnerobj(self), name)
>     def __setattr__(self, name, value):
>         _set(getinnerobj(self), name, value)
>     def __delattr__(self, name):
>         _del(getinnerobj(self), name)
> 
> _refset = set()
> 
> class Finalized(object):
>     def __new__(cls, *args, **kw):
>         self = super(Finalized, cls).__new__(cls, *args, **kw)
>         self.__init__(*args, **kw)
>         def finalize(ref, refset=_refset):
>             refset.remove(ref)
>             cls.__finalize__(self)
>         fake = Impostor(self)
>         _refset.add(weakref.ref(fake, finalize))
>         return fake
>     def __finalize__(self):
>         pass

The problem here is that __getattribute__ doesn't work for things like 
__getitem__.  So the fake object can't properly delegate these::

     >>> class C(Finalized):
     ...     def __getitem__(self, key):
     ...         return key
     ...
     >>> c = C()
     >>> c[1]
     Traceback (most recent call last):
       File "<interactive input>", line 1, in <module>
     TypeError: 'Impostor' object is unindexable

AFAIK, with new-style classes, there is no way to do this kind of 
delegation properly.

STeVe



More information about the Python-list mailing list