Automatic delegation in Python 3

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Wed Sep 8 15:58:05 CEST 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