Adding modified methods from another class without subclassing

Steven D'Aprano steve+comp.lang.python at pearwood.info
Tue Aug 23 03:25:22 EDT 2011


On Mon, 22 Aug 2011 11:08 pm John O'Hagan wrote:

> On Mon, 22 Aug 2011 15:27:36 +1000
> Steven D'Aprano <steve+comp.lang.python at pearwood.info> wrote:
[...]
>> # Untested
>> class MySeq(object):
>>     methods_to_delegate = ('__getitem__', '__len__', ...)
>>     pitches = ...  # make sure pitches is defined
>>     def __getattr__(self, name):
>>         if name in self.__class__.methods_to_delegate:
>>             return getattr(self.pitches, name)
>>         return super(MySeq, object).__getattr__(self, name)
>>         # will likely raise AttributeError
> 
> Thanks, this looks promising. I didn't know about __getattr__ or
> delegation. This example doesn't seem to work as is for special methods
> beginning with "__" (e.g.: "TypeError: object of type 'MyList' has no
> len()"). It seems that __getattr__ is not called for special methods.

Ah yes, that would be a problem.

This recipe may help.

http://code.activestate.com/recipes/252151-generalized-delegates-and-proxies/


> Also, it doesn't immediately suggest to me a way of modifying method calls
> (maybe __setattr__?). 

What do you mean, "modifying method calls"?

__getattr__ doesn't know whether the method retrieved modifies the instance
or not. That's irrelevant.

__setattr__ is called when you say 

instance.attribute = value



> But it's certainly a neater way to get methods to 
> operate on the attribute. I'm looking into it, and delegation generally.
> 
> However, I don't understand what the super call is doing. If the method
> isn't delegated, shouldn't it just fall back to getattr(self, name)?

getattr(self, name) will just call self.__getattr__(name) again, which will
call getattr, and so on... leading to RecursionError.



-- 
Steven




More information about the Python-list mailing list