deferred decorator

Nick Coghlan ncoghlan at iinet.net.au
Thu Dec 9 10:34:49 CET 2004


Bryan wrote:
> Nick Coghlan wrote:
> 
>> Bryan wrote:
>>
>>> i'm also curious if it's possible to write this recipe using the new 
>>> class style for the Deffered class.    it appears you can nolonger 
>>> delegate all attributes including special methods to the contained 
>>> object by using the __getattr__ or the new __getattribute__ methods.  
>>> does anyone know how to port this recipe to the new class style?
>>
>>
>>
>> Override __getattribute__. I don't know why you think it doesn't let 
>> you override all attribute accesses, as that's exactly what it is for.
>>
>> Cheers,
>> Nick.
>>
> 
> here's an example. __getattribute__ gets called for x but not for the 
> special method __add__.  and the __str__ method was found in the base 
> class object which printed the memory location, but didn't call 
> __getattribute__.  so __getattribute__ cannot be used to capture special 
> methods and delegate them to an encapsulated object.   this is why i'm 
> asking what the technique using new classes would be for this recipe.

Hmm, good point. I now have a vague idea why it happens that way, too 
(essentially, it appears the setting of the magic methods causes the interpreter 
to be notified that the object has a Python-defined method to call. With only 
__getattribute__ defined, that notification doesn't happen for all of the other 
magic methods).

This actually makes sense - otherwise how would the method which implements 
__getattribute__ be retrieved?

Similarly, in the existing recipe, none of __init__, __call__, __coerce__ or 
__getattr__ are delegated - the behaviour is actually consistent for all magic 
methods (I'm curious how the existing recipe actually works - it seems the use 
of "self.runfunc" in __call__ should get delegated. It obviously isn't, though).

Something like the following might work (I haven't tested it though):

   class Deferred(object):
     ...

   def lookup_magic(f_name):
     def new_f(self, *args, **kwargs):
       return getattr(self, f_name)(*args, **kwargs)
     return new_f

   func_list = ['__add__', '__radd__', ...]
   for f_name in func_list:
     setattr(Deferred, f_name) = lookup_magic(f_name)

A metaclass may actually provide a cleaner solution, but I'm not quite sure 
where to start with that.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at email.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://boredomandlaziness.skystorm.net



More information about the Python-list mailing list