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

AltStyle によって変換されたページ (->オリジナル) /