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

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to