473,569 Members | 2,400 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

inheritance problem with 2 cooperative methods

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(sel f, 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.

Dan
Jul 18 '05 #1
8 1537
Dan Perl wrote:
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)


One way would be to make the setConfig call only
in the root class, and perform the initialisation
that it depends on *before* making the super call
in each __init__ method, i.e.

class A (object):
def __init__(self, config):
self.x = 0
self.setConfig( config)

class B (A):
def __init__(self, config):
self.y = 0
super(B, self).__init__( config)

class C (B):
def __init__(self, config):
self.z = 0
super(C, self).__init__( config)

This works here because each of the initialisation
operations is self-contained. It might not work so well
in real life if some of the base class state needs to be
initialised before the subclass initialisation can be
performed. However, it's worth considering -- I came
across the same sort of problem several times in
PyGUI, and I usually managed to solve it by carefully
arranging initialisations before and after the super
call.

If you can't use that solution, I would suggest you
keep the __init__ and setConfig operations separate,
and live with having to call setConfig after creating
an object. Factory functions could be provided if
you were doing this a lot.

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Jul 18 '05 #2
Dan Perl wrote:
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)


One way would be to make the setConfig call only
in the root class, and perform the initialisation
that it depends on *before* making the super call
in each __init__ method, i.e.

class A (object):
def __init__(self, config):
self.x = 0
self.setConfig( config)

class B (A):
def __init__(self, config):
self.y = 0
super(B, self).__init__( config)

class C (B):
def __init__(self, config):
self.z = 0
super(C, self).__init__( config)

This works here because each of the initialisation
operations is self-contained. It might not work so well
in real life if some of the base class state needs to be
initialised before the subclass initialisation can be
performed. However, it's worth considering -- I came
across the same sort of problem several times in
PyGUI, and I usually managed to solve it by carefully
arranging initialisations before and after the super
call.

If you can't use that solution, I would suggest you
keep the __init__ and setConfig operations separate,
and live with having to call setConfig after creating
an object. Factory functions could be provided if
you were doing this a lot.

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Jul 18 '05 #3
Thank you very much, Greg, that does the job! Somehow I couldn't see it and
I needed someone to point out to me.

Dan

"Greg Ewing" <gr**@cosc.cant erbury.ac.nz> wrote in message
news:31******** *****@individua l.net...
Dan Perl wrote:
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)


One way would be to make the setConfig call only
in the root class, and perform the initialisation
that it depends on *before* making the super call
in each __init__ method, i.e.

class A (object):
def __init__(self, config):
self.x = 0
self.setConfig( config)

class B (A):
def __init__(self, config):
self.y = 0
super(B, self).__init__( config)

class C (B):
def __init__(self, config):
self.z = 0
super(C, self).__init__( config)

This works here because each of the initialisation
operations is self-contained. It might not work so well
in real life if some of the base class state needs to be
initialised before the subclass initialisation can be
performed. However, it's worth considering -- I came
across the same sort of problem several times in
PyGUI, and I usually managed to solve it by carefully
arranging initialisations before and after the super
call.

If you can't use that solution, I would suggest you
keep the __init__ and setConfig operations separate,
and live with having to call setConfig after creating
an object. Factory functions could be provided if
you were doing this a lot.

--
Greg Ewing, Computer Science Dept,
University of Canterbury, Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Jul 18 '05 #4
Thank you very much, Greg, that does the job! Somehow I couldn't see it and
I needed someone to point out to me.

Dan

"Greg Ewing" <gr**@cosc.cant erbury.ac.nz> wrote in message
news:31******** *****@individua l.net...
Dan Perl wrote:
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)


One way would be to make the setConfig call only
in the root class, and perform the initialisation
that it depends on *before* making the super call
in each __init__ method, i.e.

class A (object):
def __init__(self, config):
self.x = 0
self.setConfig( config)

class B (A):
def __init__(self, config):
self.y = 0
super(B, self).__init__( config)

class C (B):
def __init__(self, config):
self.z = 0
super(C, self).__init__( config)

This works here because each of the initialisation
operations is self-contained. It might not work so well
in real life if some of the base class state needs to be
initialised before the subclass initialisation can be
performed. However, it's worth considering -- I came
across the same sort of problem several times in
PyGUI, and I usually managed to solve it by carefully
arranging initialisations before and after the super
call.

If you can't use that solution, I would suggest you
keep the __init__ and setConfig operations separate,
and live with having to call setConfig after creating
an object. Factory functions could be provided if
you were doing this a lot.

--
Greg Ewing, Computer Science Dept,
University of Canterbury, Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Jul 18 '05 #5
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(sel f, 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.configinit ialized = False
super(A, self).__init__( )
if not self.configinit ialized:
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
Jul 18 '05 #6
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(sel f, 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.configinit ialized = False
super(A, self).__init__( )
if not self.configinit ialized:
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
Jul 18 '05 #7
This is almost the same code as Greg's with the only difference being that
test for configuration having been done. But the test is unnecessary. I
don't see how setConfig could be invoked in the super of the base class (A),
so such a test would be relevant only in subclasses, if they DO invoke
setConfig. But it's better if they just don't invoke it, which makes for a
much cleaner solution. Thanks anyway.

BTW, you named the attribute configinitializ ed in one place and configSet in
the other place. Which proves that the test is redundant, because it does
work anyway as is.

I had a similar solution, where I was invoking setConfig only if the class
of self is the same as the class where __init__ is defined, something like
this:
class A (object):
def __init__(self, config):
self.x = 0
super(A, self).__init__( )
if A == self.__class__:
self.setConfig( config)

I didn't like it though because it has to be done like this in every
subclass's __init__. And it's a problem that I didn't realize at the time
if a subclass just does not need to override __init__ (then the
configuration is just not set).

Dan

"David Fraser" <da****@sjsoft. com> wrote in message
news:co******** **@ctb-nnrp2.saix.net. ..

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.configinit ialized = False
super(A, self).__init__( )
if not self.configinit ialized:
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

Jul 18 '05 #8
This is almost the same code as Greg's with the only difference being that
test for configuration having been done. But the test is unnecessary. I
don't see how setConfig could be invoked in the super of the base class (A),
so such a test would be relevant only in subclasses, if they DO invoke
setConfig. But it's better if they just don't invoke it, which makes for a
much cleaner solution. Thanks anyway.

BTW, you named the attribute configinitializ ed in one place and configSet in
the other place. Which proves that the test is redundant, because it does
work anyway as is.

I had a similar solution, where I was invoking setConfig only if the class
of self is the same as the class where __init__ is defined, something like
this:
class A (object):
def __init__(self, config):
self.x = 0
super(A, self).__init__( )
if A == self.__class__:
self.setConfig( config)

I didn't like it though because it has to be done like this in every
subclass's __init__. And it's a problem that I didn't realize at the time
if a subclass just does not need to override __init__ (then the
configuration is just not set).

Dan

"David Fraser" <da****@sjsoft. com> wrote in message
news:co******** **@ctb-nnrp2.saix.net. ..

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.configinit ialized = False
super(A, self).__init__( )
if not self.configinit ialized:
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

Jul 18 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
3229
by: Ricky Romaya | last post by:
Hi, Are there any ways to get multiple inheritace in PHP4? For example, I have 3 parent class, class A, B, and C. I want class X to inherit all those 3 classes. Consider merging those 3 classes is out of the question, as there are class Y which only inherits from class A, etc. TIA
0
412
by: Dan Perl | last post by:
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):...
14
6385
by: Axel Straschil | last post by:
Hello! Im working with new (object) classes and normaly call init of ther motherclass with callin super(...), workes fine. No, I've got a case with multiple inherance and want to ask if this is the right and common case to call init: class Mother(object): def __init__(self, param_mother): print 'Mother'
13
3269
by: John Perks and Sarah Mount | last post by:
Trying to create the "lopsided diamond" inheritance below: >>> class B(object):pass >>> class D1(B):pass >>> class D2(D1):pass >>> class D(D1, D2):pass Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: Error when calling the metaclass bases Cannot create a consistent method resolution
20
10046
by: km | last post by:
Hi all, In the following code why am i not able to access class A's object attribute - 'a' ? I wishto extent class D with all the attributes of its base classes. how do i do that ? thanks in advance for enlightment ... here's the snippet #!/usr/bin/python
4
2745
by: Alex Hunsley | last post by:
I've seen a few discussion about the use of 'super' in Python, including the opinion that 'super' should only be used to solve inheritance diamond problem. (And that a constructor that wants to call the superclass methods should just call them by name and forget about super.) What is people's opinion on this? Does it make any sense?
14
12891
by: Steve Jorgensen | last post by:
Recently, I tried and did a poor job explaining an idea I've had for handling a particular case of implementation inheritance that would be easy and obvious in a fully OOP language, but is not at all obvious in VBA which lacks inheritance. I'm trying the explanation again now. I often find cases where a limited form of inheritance would...
5
2808
by: Thomas Girod | last post by:
Hi. I think I'm missing something about multiple inheritance in python. I've got this code. class Foo: def __init__(self): self.x = "defined by foo" self.foo = None
6
1862
by: burningodzilla | last post by:
Hi all - I'm preparing to dive in to more complex application development using javascript, and among other things, I'm having a hard time wrapping my head around an issues regarding "inheritance" using the prototype property. I realize there are no classes in JS, that code therefore lives in objects instead of class definitions, and that...
3
4826
by: johanatan | last post by:
When I first heard about these new features, I was very excited as it would have (if implemented as I had expected) rendered mimicking multiple inheritance almost painless in C#. Unfortunately, due to a couple limitations of the language, MI is still not attainable (at least not succinctly). 1 - Interfaces cannot define data (only...
0
7703
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7926
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8138
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
6287
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5223
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3657
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
1
2117
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1228
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
946
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.