deferred decorator
Nick Coghlan
ncoghlan at iinet.net.au
Thu Dec 9 04:34:49 EST 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