Default attribute in base class precludes delegation

Bengt Richter bokr at oz.net
Fri Dec 19 01:38:59 EST 2003


On Fri, 19 Dec 2003 02:33:59 -0300, Gabriel Genellina <gagenellina at softlab.com.ar> wrote:

>At 19/12/2003 00:02, you wrote:
>
>>>class Worker:
>>>     def __init__(self, foo, bar):
>>>         self.foo = foo
>>>         self.bar = bar
>>>
>>>class Base:
>>>     bar = None
>>>
>>>class Derived(Base):
>>>     def __init__(self, worker):
>>>         self.worker = worker
>>>     def __getattr__(self, name):
>>>         return getattr(self.worker, name)
>>>w = Worker(1234, 'Hello')
>>>print 'w.foo', w.foo    # prints 1234
>>>print 'w.bar', w.bar    # prints Hello
>>>d = Derived(w)
>>>print 'd.foo',d.foo     # prints 1234
>>>print 'd.bar',d.bar     # prints None, I want to get Hello
>>
>>As you already found out, d.bar looks up Base.bar, and __getattr__ isn't 
>>invoked (since it is only called if an attribute is *not* found).
>>
>>The easiest solution might be, to change the name of the attribute 'bar' 
>>in Worker, since you can modify this class.  If at all possible, make sure 
>>it has no attribute names that are defined in Base also.  Is this an 
>>acceptable solution for you?  It sounds cheesy, but it might be better 
>>than inventing all kinds of twisted code constructs to get around this problem.
>
>That won't work, unfortunately. Other code expects Derived to have a 'bar' 
>attribute (since it inherits from Base).
>
>My workaround was to *really* set an instance attribute 'bar' in Derived, 
>and try to ensure that it's always in sync with Worker:
>
>         def __init__(self, worker):
>                 self.worker = worker
>                 self.bar = worker.bar
>
>         def setBar(self, bar):
>                 self.worker.bar = bar
>                 self.bar = bar
>
>This works if a) all people always use setBar on Derived, and b) no one 
>assigns to worker.bar directly.
>I would like another way, more "automatic", where people dont have to 
>"remember" these rules...
>(BTW, the real attribute name is 'title', wich is used all around the 
>system, that's why it's a bit difficult to assert the above rules everywhere)
>
>
If you change the Derived class in your original post (and above) to:

class Derived(object,Base):
     def __init__(self, worker):
         self.worker = worker

     def __getattribute__(self, name):
         return getattr(object.__getattribute__(self, '__dict__')['worker'], name)


I think it will get all the attributes, for better or worse, from worker (and the output
you wanted). You'll have to sort out what names you might want to deal with differently, though ;-)

Regards,
Bengt Richter




More information about the Python-list mailing list