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
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to