inheritance problem with 2 cooperative methods
David Fraser
davidf at sjsoft.com
Fri Dec 3 04:18:49 EST 2004
Dan Perl wrote:
> Here is a problem I am having trouble with and I hope someone in this group
> will suggest a solution. First, some code that works. 3 classes that are
> derived from each other (A->B->C), each one implementing only 2 methods,
> __init__ and setConfig.
> -------------------------------------------------------
> #!/usr/bin/python
> class A (object):
> def __init__(self):
> super(A, self).__init__()
> self.x = 0
> def setConfig(self, config):
> self.x += config['x']
>
> class B (A):
> def __init__(self):
> super(B, self).__init__()
> self.y = 0
> def setConfig(self, config):
> super(B, self).setConfig(config)
> self.y += config['y']
>
> class C (B):
> def __init__(self):
> super(C, self).__init__()
> self.z = 0
> def setConfig(self, config):
> super(C, self).setConfig(config)
> self.z += config['z']
>
> config = {'x':1, 'y':2, 'z':3}
> alpha = A()
> alpha.setConfig(config)
> print alpha.x
> beta = B()
> beta.setConfig(config)
> print beta.x, beta.y
> beta.setConfig(config)
> print beta.x, beta.y
> gamma = C()
> gamma.setConfig(config)
> print gamma.x, gamma.y, gamma.z
> gamma.setConfig(config)
> print gamma.x, gamma.y, gamma.z
> --------------------------------------------------
>
> The output from that code is:
> 1
> 1 2
> 2 4
> 1 2 3
> 2 4 6
>
> So far, so good! But let's assume that I want to change the __init__
> methods so that they take a configuration as an argument so the objects are
> created and configured in one step, like this:
> alpha = A(config)
>
> How can the code be changed to implement this? It is tempting to modify the
> __init__ methods like this:
> class A (object):
> def __init__(self, config):
> super(A, self).__init__(config)
> self.x = 0
> A.setConfig(self, config)
>
> However, if implemented this way, the output is:
> 1
> 2 2
> 3 4
> 3 4 3
> 4 6 6
>
> This shows that setConfig gets called more than once because both __init__
> and setConfig are cooperative methods.
>
> I have been thinking about this for a day now and I cannot find a good
> solution. I imagine this would be a common problem and that there would be
> a recipe somewhere, but I couldn't find one (I looked in the Python
> Cookbook). I've thought of creating 2 separate methods instead of
> setConfig, one that does the "local" configuration and another one that
> takes care of invoking super. But I don't like the idea of creating 2
> methods in each class and I haven't been able to think of a way to solve the
> problem with just one change in the base class that would be inherited by
> all the subclasses.
>
> Anyone has any ideas? Thanks.
What about using an attribute in the base class to remember whether
initial config has been done? This seems to work:
#!/usr/bin/python
class A (object):
def __init__(self, config):
self.x = 0
self.configinitialized = False
super(A, self).__init__()
if not self.configinitialized:
self.setConfig(config)
def setConfig(self, config):
self.x += config['x']
self.configset = True
class B (A):
def __init__(self, config):
self.y = 0
super(B, self).__init__(config)
def setConfig(self, config):
super(B, self).setConfig(config)
self.y += config['y']
class C (B):
def __init__(self, config):
self.z = 0
super(C, self).__init__(config)
def setConfig(self, config):
super(C, self).setConfig(config)
self.z += config['z']
config = {'x':1, 'y':2, 'z':3}
alpha = A(config)
print alpha.x
beta = B(config)
print beta.x, beta.y
beta.setConfig(config)
print beta.x, beta.y
gamma = C(config)
print gamma.x, gamma.y, gamma.z
gamma.setConfig(config)
print gamma.x, gamma.y, gamma.z
More information about the Python-list
mailing list