473,320 Members | 1,945 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Dispatch with multiple inheritance

Consider the following class hierarchy in Python:

class A (object):
def __init__(self):
print "cons A"

class B (object):
def __init__(self):
print "cons B"

class C (A):
def __init__(self):
super(C, self).__init__()
print "cons C"

class D (B):
def __init__(self):
super(D, self).__init__()
print "cons D"

Now, suppose I would like to define a new class as follows:

class E (C, D):
...

In the constructor for E, I would like to invoke the constructors of
both parent classes. The correct way to do this seems to be exemplified
by the following:

class E (C, D):
def __init__(self):
super(E, self).__init__() # calls C constructor
super(A, self).__init__() # calls D constructor (**)
print "cons E"

This works, but I find it somewhat troubling. It seems to me that one
should not have to "know" (i.e., write down the names of) the ancestors
of C in order to dispatch to superclass methods in D, since C and D
share no common ancestors south of object.

Is there a better (i.e., more elegant) way to handle the case marked
(**) above?

Curious,
-M

--
Michael J. Fromberger | Lecturer, Dept. of Computer Science
http://www.dartmouth.edu/~sting/ | Dartmouth College, Hanover, NH, USA
Jul 18 '06 #1
8 1468
Michael,
You only need to call the __init__ method of the superclass if you need
to do something special during initialization. In general I just use
the SuperClass.__init__(self,...) way of calling the super class
constructors. This way, I only initialize the immediate parents and
they will in turn call the init method of their parents and so on.
super() is probably the a better way to do things but I find
SuperClass.__init__(self, ...) more clear. For example your code would
be:
-------------------------------
class A (object):
def __init__(self):
print "cons A"

class B (object):
def __init__(self):
print "cons B"

class C (A):
def __init__(self):
A.__init__(self)
print "cons C"

class D (B):
def __init__(self):
B.__init__(self)
print "cons D"

class E(D,C):
def __init__(self):
C.__init__(self)
D.__init__(self)
print "cons E"

e=E()
----------------------------------
Output should be:
cons A
cons C
cons B
cons D
cons E

In general note that __init__ is NOT a constuctor it is an initializer
(therefore the name __init__ as opposed to __constr__ or __new__). The
object is constructed by Python already and is given to init method as
the 'self' argument. The construction can also be customized inside the
__new__ magic method, but normally you don't even need to know about
__new__.

Hope this helps,
Nick V.

Michael J. Fromberger wrote:
Consider the following class hierarchy in Python:

class A (object):
def __init__(self):
print "cons A"

class B (object):
def __init__(self):
print "cons B"

class C (A):
def __init__(self):
super(C, self).__init__()
print "cons C"

class D (B):
def __init__(self):
super(D, self).__init__()
print "cons D"

Now, suppose I would like to define a new class as follows:

class E (C, D):
...

In the constructor for E, I would like to invoke the constructors of
both parent classes. The correct way to do this seems to be exemplified
by the following:

class E (C, D):
def __init__(self):
super(E, self).__init__() # calls C constructor
super(A, self).__init__() # calls D constructor (**)
print "cons E"

This works, but I find it somewhat troubling. It seems to me that one
should not have to "know" (i.e., write down the names of) the ancestors
of C in order to dispatch to superclass methods in D, since C and D
share no common ancestors south of object.

Is there a better (i.e., more elegant) way to handle the case marked
(**) above?

Curious,
-M

--
Michael J. Fromberger | Lecturer, Dept. of Computer Science
http://www.dartmouth.edu/~sting/ | Dartmouth College, Hanover, NH, USA
Jul 18 '06 #2
Michael J. Fromberger ha scritto:
Consider the following class hierarchy in Python:
<snip>
Is there a better (i.e., more elegant) way to handle the case marked
(**) above?

Curious,
-M

--
Michael J. Fromberger | Lecturer, Dept. of Computer Science
http://www.dartmouth.edu/~sting/ | Dartmouth College, Hanover, NH, USA
Look at
http://www.python.org/download/releases/2.3/mro
Michele Simionato

Jul 19 '06 #3
Michael J. Fromberger wrote:
>
Is there a better (i.e., more elegant) way to handle the case marked
(**) above?
You have to call super in each method __init__, if you don't, the call
chain break before the end:

class A (object):
def __init__(self):
super(A, self).__init__()
print "cons A"

class B (object):
def __init__(self):
super(B, self).__init__()
print "cons B"

class C (A):
def __init__(self):
super(C, self).__init__()
print "cons C"

class D (B):
def __init__(self):
super(D, self).__init__()
print "cons D"

class E (C, D):
def __init__(self):
super(E, self).__init__() # calls C constructor
print "cons E"

Jul 19 '06 #4

looping wrote:
Michael J. Fromberger wrote:

Is there a better (i.e., more elegant) way to handle the case marked
(**) above?

You have to call super in each method __init__, if you don't, the call
chain break before the end:

class A (object):
def __init__(self):
super(A, self).__init__()
print "cons A"

class B (object):
def __init__(self):
super(B, self).__init__()
print "cons B"

class C (A):
def __init__(self):
super(C, self).__init__()
print "cons C"

class D (B):
def __init__(self):
super(D, self).__init__()
print "cons D"

class E (C, D):
def __init__(self):
super(E, self).__init__() # calls C constructor
print "cons E"
After a second tought, it's probably better to call __init__ method
explicitly in class E:

class A (object):
def __init__(self):
print "cons A"

class B (object):
def __init__(self):
print "cons B"

class C (A):
def __init__(self):
super(C, self).__init__()
print "cons C"

class D (B):
def __init__(self):
super(D, self).__init__()
print "cons D"

class E (C, D):
def __init__(self):
D.__init__(self)
C.__init__(self)
print "cons E"

this way you have to choose which __init__ from class D or class C is
calling, and which is calling first.
Any Python Guru to give is opinion ?

Jul 19 '06 #5
In article <11*********************@s13g2000cwa.googlegroups. com>,
"Michele Simionato" <mi***************@gmail.comwrote:
Michael J. Fromberger ha scritto:
Consider the following class hierarchy in Python:
<snip>
Is there a better (i.e., more elegant) way to handle the case marked
(**) above?

Curious,
-M

--
Michael J. Fromberger | Lecturer, Dept. of Computer Science
http://www.dartmouth.edu/~sting/ | Dartmouth College, Hanover, NH, USA

Look at
http://www.python.org/download/releases/2.3/mro
Hi, Michele,

I understand what Python's method resolution order is, and how it is
constructed. Is there something else in that article, that you hoped
would address my original concern? In particular, I am not asking WHY
super(A, self).__init()__ yields the next method in order -- that is
quite clear. Rather, I want to know if there is a better way to invoke
the ancestry of class E from D, than to explicitly denote the ancestry
of C in the code. The latter is an ugly violation of abstraction, and
renders the class hierarchy brittle.

Of course, I could just bypass super, and explicitly invoke them as:

C.__init__(self, ...)
D.__init__(self, ...)

.... but that seems to me to defeat the purpose of having super in the
first place.

It seems as if perhaps there is no better solution at present. That is
a pity, albeit a mild one. Thank you for taking the time to respond.

-M

--
Michael J. Fromberger | Lecturer, Dept. of Computer Science
http://www.dartmouth.edu/~sting/ | Dartmouth College, Hanover, NH, USA
Jul 19 '06 #6
In article <11**********************@m73g2000cwd.googlegroups .com>,
"Nick Vatamaniuc" <va******@gmail.comwrote:
Michael,
You only need to call the __init__ method of the superclass if you need
to do something special during initialization.
Hi, Nick,

Thank you for responding. I understand the purpose in invoking the
superclasses' __init__ methods. Let us take it as a given that I
require this behaviour; the simple example does not show it, but I am
using the same technique in a much more elaborate program, where in fact
the superclass initialization is required.
In general I just use the SuperClass.__init__(self,...) way of
calling the super class constructors.
Yes, and that certainly works just fine. But it obviates the point of
having super(). But perhaps that is the take-home message.

I do not want A's constructor to dispatch further along in the MRO for E
for two reasons: One, because the constructors along the (E D B) chain
take different argument lists (in my real code) than the (E C A) path;
and two, because I happen to care about the order in which the methods
are invoked.
In general note that __init__ is NOT a constuctor it is an initializer
Yes, you're right; I apologize for the imprecision. However, for the
purposes of this example, the distinction is irrelevant.

Cheers,
-M

--
Michael J. Fromberger | Lecturer, Dept. of Computer Science
http://www.dartmouth.edu/~sting/ | Dartmouth College, Hanover, NH, USA
Jul 19 '06 #7
Michael J. Fromberger wrote:
....
>
Of course, I could just bypass super, and explicitly invoke them as:

C.__init__(self, ...)
D.__init__(self, ...)

... but that seems to me to defeat the purpose of having super in the
first place.
As others have pointed out, super, is designed to do something different from
what you want. See
http://www.python.org/download/relea...o/#cooperation for GvR's
explanation of super's intent, limitations, and a pure-python implementation
that you might alter for your purposes.

Some people argue that effective use cases for super are rare and that it's
awkward to use correctly even in these cases. See for example,
http://fuhm.net/super-harmful/. So don't feel bad about not using it ;-)

Given what you assert about your inheritance graph (two independent ancestor
chains, that do not propagate super calls from their respective base classes),
what is objectionable about:
C.__init__(self, ...)
D.__init__(self, ...)
Michael
Jul 19 '06 #8
In article <ma***************************************@python. org>,
Michael Spencer <ma**@telcopartners.comwrote:
As others have pointed out, super, is designed to do something different from
what you want. See
http://www.python.org/download/relea...o/#cooperation for
GvR's
explanation of super's intent, limitations, and a pure-python
implementation
that you might alter for your purposes.
Indeed so. The documentation for super() led me to an erroneous
conclusion.
Given what you assert about your inheritance graph (two independent ancestor
chains, that do not propagate super calls from their respective base
classes),
what is objectionable about:
C.__init__(self, ...)
D.__init__(self, ...)
Well, since super() were much better labelled call_next_method, I must
agree that the Class.__init__(self, ...) form is probably the best
solution!

Thanks for your feedback.

Cheers,
-M

--
Michael J. Fromberger | Lecturer, Dept. of Computer Science
http://www.dartmouth.edu/~sting/ | Dartmouth College, Hanover, NH, USA
Jul 20 '06 #9

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

Similar topics

2
by: Graham Banks | last post by:
Does using multiple inheritance introduce any more performance overhead than single inheritance?
4
by: Leslaw Bieniasz | last post by:
Cracow, 20.09.2004 Hello, I need to implement a library containing a hierarchy of classes together with some binary operations on objects. To fix attention, let me assume that it is a...
5
by: Morgan Cheng | last post by:
It seems no pattern defined by GoF takes advantage of multiple inheritance. I am wondering if there is a situation where multiple inheritance is a necessary solution. When coding in C++, should...
22
by: Matthew Louden | last post by:
I want to know why C# doesnt support multiple inheritance? But why we can inherit multiple interfaces instead? I know this is the rule, but I dont understand why. Can anyone give me some concrete...
47
by: Mark | last post by:
why doesn't .NET support multiple inheritance? I think it's so silly! Cheers, Mark
60
by: Shawnk | last post by:
Some Sr. colleges and I have had an on going discussion relative to when and if C# will ever support 'true' multiple inheritance. Relevant to this, I wanted to query the C# community (the...
3
by: tyler.schlosser | last post by:
Hi there, I am trying to launch a program called AmiBroker using the command: AB = win32com.client.Dispatch("Broker.Application") However, I have a dual-core CPU and would like to launch two...
3
by: Tigera | last post by:
Greetings, I too have succumbed to the perhaps foolish urge to write a video game, and I have been struggling with the implementation of multiple dispatch. I read through "More Effective C++"...
47
by: Larry Smith | last post by:
I just read a blurb in MSDN under the C++ "ref" keyword which states that: "Under the CLR object model, only public single inheritance is supported". Does this mean that no .NET class can ever...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....

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.