Automatic delegation in Python 3

Terry Reedy tjreedy at udel.edu
Wed Sep 8 21:45:46 CEST 2010


On 9/8/2010 9:58 AM, Steven D'Aprano wrote:
> Delegation in old-style classes worked fine:
>
> # Python 2.6
>>>> class Delegate:
> ...     def __init__(self, x):
> ...             self.__dict__['x'] = x
> ...     def __getattr__(self, name):
> ...             return getattr(self.x, name)
> ...     def __setattr__(self, name, value):
> ...             setattr(self.x, name, value)
> ...
>>>> obj = Delegate({})
>>>> obj[1] = None

Since you are not setting a attribute, I was initially surprised that 
this worked. Then I remembered that this is executed for old-style 
classes as
obj.__getattr__('__setitem__')(1,None)
and that __setattr__ above is not involved.

This is possible because old-style user classes were a world apart form 
builtin types. Once user-classes were integrated into the builting 
class/type hierarchy, they had to follow the same rules as the latter. 
One problem is that classes are also instances of their metaclass. This 
is somewhat explained in 3.3.8 'Special method lookup' (which I have 
read at least 3 times before understanding).

As you discovered, this is not a complete win. The bottom line of 3.3.8:

"Bypassing the __getattribute__() machinery in this fashion provides 
significant scope for speed optimisations within the interpreter, at the 
cost of some flexibility in the handling of special methods (the special 
method must be set on the class object itself in order to be 
consistently invoked by the interpreter)."

You are seeing the cost.

> Unfortunately, I need to use delegation, not inheritance, and I need to
> use a new-style class, since I will be using Python 3. How can I do
> automatic delegation in Python 3? Is my only hope to give up on the
> elegance of automatic delegation, and code all the special methods as
> manual delegation?

Based on the above, it seems so. But I would search a bit more for 
delegation and proxy object and python 3 to see what others have done.

-- 
Terry Jan Reedy




More information about the Python-list mailing list