inheritance problem with 2 cooperative methods

David Fraser davidf at sjsoft.com
Fri Dec 3 10:18:49 CET 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