Default attribute in base class precludes delegation
Bengt Richter
bokr at oz.net
Fri Dec 19 00:41:01 EST 2003
On Fri, 19 Dec 2003 00:44:28 -0300, Gabriel Genellina <gagenellina at softlab.com.ar> wrote:
>Hi
>
>In the following code sample, I have:
>- a Worker class, which could have a lot of methods and attributes. In
>particular, it has a 'bar' attribute. This class can be modified as needed.
>- a Base class (old-style) which defines a default class attribute 'bar'
>too. I can't modify the source code of this class. Note that Workes does
>not inherit from Base.
>- a Derived class which must inherit from Base and is a wrapper around
>Worker: it contains a Worker instance and delegates almost anything to it.
>This class can be modified as needed too.
In what sense a "wrapper"?
>
>For most attributes, as they are not found in the Derived instance's dict,
>__getattr__ is called and the attribute is retrieved from the Worker instance.
Why do you (think you) need an explicit __getattr__ ? Usually there's better ways.
>But for the 'bar' attribute, it is found in the Base class and just the
>default value is returned. __getattr__ is never called.
>I need to avoid this, and return Worker instance's value instead of Base's
>default value.
>That is, in the last line of the example, I want: d.bar == 'Hello'
>How could it be done?
>
>--- cut ---
># This class does the "real" work and I can modify it as needed
>class Worker:
class Worker(object):
> def __init__(self, foo, bar):
> self.foo = foo
> self.bar = bar
>
># This is just a base class from which I must inherit but I can't modify it
>class Base:
> bar = None
>
># This is a wrapper for Worker and I can modify it.
># I want to get most attributes from Worker class
># but for 'bar' I always get the default from Base,
># its declaration there effectively hides the attribute
># from the delegated Worked instance.
>class Derived(Base):
class Derived(Worker, Base):
"""never mind any methods at this point yet"""
> 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)
d = Derived(6578, 'Goodbye')
>print 'd.foo',d.foo # prints 1234
>print 'd.bar',d.bar # prints None, I want to get Hello
>
>--- cut ---
Does this do anything for you? (you could inherit differently than below too, of course)
====< genellina.py >=========================================================================
# This class does the "real" work and I can modify it as needed
class Worker(object):
def __init__(self, foo, bar):
print 'Worker init: Initializing %s instance' % self.__class__.__name__
self.foo = foo
self.bar = bar
# This is just a base class from which I must inherit but I can't modify it
class Base:
def __init__(self,*args, **kw): print 'Base init:', args, kw
bar = None
baz = 'Base baz'
# This is a wrapper for Worker and I can modify it.
# I want to get most attributes from Worker class
##### why not just inherit them from ^^^^^^^^^^^^ ?
# but for 'bar' I always get the default from Base,
# its declaration there effectively hides the attribute
# from the delegated Worked instance.
class Derived(Worker, Base):
"""dummy until something to do"""
if __name__ == '__main__':
w = Worker(1234, 'Hello')
print 'w.foo of %s instance: %s' %(w.__class__.__name__, w.foo) # prints 1234 now
print 'w.bar of %s instance: %s' %(w.__class__.__name__, w.bar) # prints Hello now
d = Derived(5678, 'Goodbye') #w)
print 'd.foo of %s instance: %s' %(d.__class__.__name__, d.foo) # prints 5678 now
print 'd.bar of %s instance: %s' %(d.__class__.__name__, d.bar) # prints Goodbye now
print 'd.baz of/via %s instance: %s' %(d.__class__.__name__, d.baz)
d.baz = 'd instance baz'
print 'd.baz of/via %s instance: %s' %(d.__class__.__name__, d.baz)
=============================================================================================
Result:
[21:52] C:\pywk\clp>genellina.py
Worker init: Initializing Worker instance
w.foo of Worker instance: 1234
w.bar of Worker instance: Hello
Worker init: Initializing Derived instance
d.foo of Derived instance: 5678
d.bar of Derived instance: Goodbye
d.baz of/via Derived instance: Base baz
d.baz of/via Derived instance: d instance baz
Or do you actually need to have different unknown types of workers so you can't inherit?
Regards,
Bengt Richter
More information about the Python-list
mailing list