Automatic delegation in Python 3
Steven D'Aprano
steve at REMOVE-THIS-cybersource.com.au
Wed Sep 8 09:58:05 EDT 2010
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
>>> obj
{1: None}
But when I try the equivalent recipe with a new-style class, it behaves
differently:
>>> class Delegate2(object):
... 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 = Delegate2({})
>>> obj
<__main__.Delegate2 object at 0x8f6130c>
Okay, I get that one... because I'm inheriting from object, __getattr__
picks up object's __str__ method and uses that.
But then there's this:
>>> obj[1] = 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'Delegate2' object does not support item assignment
But these work:
>>> obj.__setitem__
<method-wrapper '__setitem__' of dict object at 0xb7c6902c>
>>> obj.__setitem__(1, None)
>>> obj.x
{1: None}
What's going on here? I *think* this has something to do with special
double-underscore methods being looked up on the class, not the instance,
for new-style classes, but I'm not entirely sure.
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?
class Delegate2(object):
def __setitem__(self, key, value):
self.x[key] = value
# and so on for everything else I care about...
--
Steven
More information about the Python-list
mailing list