Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Re: Multiple inheritance with a common base class

Reply
Thread Tools

Re: Multiple inheritance with a common base class

 
 
Markus Bertheau
Guest
Posts: n/a
 
      08-10-2004
В Втр, 10.08.2004, в 13:37, Markus Bertheau пишет:

Also I observe that the instance will in fact _not_ have a single copy
of the data attributes used by the common base class. The following
example demonstrates this:

class CommonBase:
def __init__(self):
self.no = 0
def setNo(self, no):
self.no = no

class LeafA(CommonBase):
def __init__(self):
CommonBase.__init__(self)
print("CommonBase.no: %i" % self.no)
CommonBase.setNo(self, 3)

class LeafB(CommonBase):
def __init__(self):
CommonBase.__init__(self)
print("CommonBase.no: %i" % self.no)
CommonBase.setNo(self, 4)

class Multi(LeafA, LeafB):
def __init__(self):
LeafA.__init__(self)
LeafB.__init__(self)

m = Multi()

It outputs:

CommonBase.no: 0
CommonBase.no: 0

If there was only one copy of the common base class, I'd have expected
an output similar to

CommonBase.no: 0
CommonBase.no: 3

This renders multiple inheritance pretty useless for me.

Can someone clear this all up and tell me how multiple inheritance is
supposed to work in python?

Thanks

--
Markus Bertheau <(E-Mail Removed)>

 
Reply With Quote
 
 
 
 
Duncan Booth
Guest
Posts: n/a
 
      08-10-2004
Markus Bertheau <(E-Mail Removed)> wrote in
news:(E-Mail Removed):

> It outputs:
>
> CommonBase.no: 0
> CommonBase.no: 0
>
> If there was only one copy of the common base class, I'd have expected
> an output similar to
>
> CommonBase.no: 0
> CommonBase.no: 3
>
> This renders multiple inheritance pretty useless for me.
>
> Can someone clear this all up and tell me how multiple inheritance is
> supposed to work in python?


Well of course it outputs 0 twice. That's because after LeafA initialised
CommonBase, and set its value to 3 you then reinitialised it from LeafB and
set the value back to 0.

Do this instead:

class CommonBase:
def __init__(self):
self.no = 0
def setNo(self, no):
self.no = no

class LeafA(CommonBase):
def __init__(self):
super(LeafA, self).__init__()
print("LeafA:CommonBase.no: %i" % self.no)
CommonBase.setNo(self, 3)

class LeafB(CommonBase):
def __init__(self):
super(LeafB, self).__init__()
print("LeafB:CommonBase.no: %i" % self.no)
CommonBase.setNo(self, 4)

class Multi(LeafA, LeafB):
def __init__(self):
super(Multi, self).__init__()

m = Multi()

Which gives you the output:

LeafB:CommonBase.no: 0
LeafA:CommonBase.no: 4

Using super will ensure that you get a reliable chain of method calls. In
this case it means that Multi.__init__ calls LeafA.__init__ which calls
LeafB.__init__ which then calls CommonBase.__init__. Note that LeafA
propogates the call to LeafB even though LeafA has no knowledge of the
existence of LeafB.
 
Reply With Quote
 
 
 
 
Peter Otten
Guest
Posts: n/a
 
      08-10-2004
Markus Bertheau wrote:

> ? ???, 10.08.2004, ? 13:37, Markus Bertheau ?????:
>
> Also I observe that the instance will in fact _not_ have a single copy
> of the data attributes used by the common base class. The following
> example demonstrates this:
>
> class CommonBase:
> def __init__(self):
> self.no = 0
> def setNo(self, no):
> self.no = no
>
> class LeafA(CommonBase):
> def __init__(self):
> CommonBase.__init__(self)
> print("CommonBase.no: %i" % self.no)
> CommonBase.setNo(self, 3)
>
> class LeafB(CommonBase):
> def __init__(self):
> CommonBase.__init__(self)
> print("CommonBase.no: %i" % self.no)
> CommonBase.setNo(self, 4)
>
> class Multi(LeafA, LeafB):
> def __init__(self):
> LeafA.__init__(self)


insert

print self.no

to verify that at this point self.no is indeed 3. LeafB.__init__() then
calls CommonBase.__init__() which in turn sets self.no to 0 again.

> LeafB.__init__(self)
>
> m = Multi()
>
> It outputs:
>
> CommonBase.no: 0
> CommonBase.no: 0
>
> If there was only one copy of the common base class, I'd have expected
> an output similar to
>
> CommonBase.no: 0
> CommonBase.no: 3
>
> This renders multiple inheritance pretty useless for me.
>
> Can someone clear this all up and tell me how multiple inheritance is
> supposed to work in python?


Remember that __init__() is just a method like any other that will be called
automaticallly after the instance is created - not a constructor. If you
call it explicitly it will be executed no matter where you are in your
program. If you want to ensure that all methods with the same name are
executed once across an inheritance hierarchy, have a look at super().

If you know some C++ it might help to regard all python base classes as
virtual.

http://www.python.org/2.2.2/descrintro.html
http://www.python.org/2.3/mro.html

might also interest you - as a bonus, the latter has some nice ascii-art

Peter

 
Reply With Quote
 
Markus Bertheau
Guest
Posts: n/a
 
      08-10-2004
В Втр, 10.08.2004, в 14:38, Duncan Booth пишет:

> Well of course it outputs 0 twice. That's because after LeafA initialised
> CommonBase, and set its value to 3 you then reinitialised it from LeafB and
> set the value back to 0.


Thanks for the explanation, Heiko too.

> Using super will ensure that you get a reliable chain of method calls. In
> this case it means that Multi.__init__ calls LeafA.__init__ which calls
> LeafB.__init__ which then calls CommonBase.__init__. Note that LeafA
> propogates the call to LeafB even though LeafA has no knowledge of the
> existence of LeafB.


That is what I needed to know. Thanks. It should probably be noted in
the paragraph about multiple inheritance.

(CommonBase has to be a new style class for python <= 2.3)

Thanks

--
Markus Bertheau <(E-Mail Removed)>

 
Reply With Quote
 
Markus Bertheau
Guest
Posts: n/a
 
      08-10-2004
В Втр, 10.08.2004, в 15:01, Markus Bertheau пишет:

> That is what I needed to know. Thanks. It should probably be noted in
> the paragraph about multiple inheritance.


Now how do I make the following work:

class CommonBase(object):
def __init__(self, c):
pass

class LeafA(CommonBase):
def __init__(self, c, a):
super(LeafA, self).__init__(c)

class LeafB(CommonBase):
def __init__(self, c, b):
super(LeafB, self).__init__(c)

class Multi(LeafA, LeafB):
def __init__(self, c, a, b):
super(Multi, self).__init__(c, a, b)

m = Multi(0, 1, 2)

Thanks

--
Markus Bertheau <(E-Mail Removed)>

 
Reply With Quote
 
Duncan Booth
Guest
Posts: n/a
 
      08-10-2004
Markus Bertheau <(E-Mail Removed)> wrote in
news:(E-Mail Removed):

> Now how do I make the following work:
>
> class CommonBase(object):
> def __init__(self, c):
> pass
>
> class LeafA(CommonBase):
> def __init__(self, c, a):
> super(LeafA, self).__init__(c)
>
> class LeafB(CommonBase):
> def __init__(self, c, b):
> super(LeafB, self).__init__(c)
>
> class Multi(LeafA, LeafB):
> def __init__(self, c, a, b):
> super(Multi, self).__init__(c, a, b)
>
> m = Multi(0, 1, 2)
>


The best way is to use keyword arguments:

class CommonBase(object):
def __init__(self, c):
pass

class LeafA(CommonBase):
def __init__(self, a, **kw):
super(LeafA, self).__init__(**kw)

class LeafB(CommonBase):
def __init__(self, b, **kw):
super(LeafB, self).__init__(**kw)

class Multi(LeafA, LeafB):
def __init__(self, **kw):
super(Multi, self).__init__(**kw)

m = Multi(c=0, a=1, b=2)
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Multiple inheritance, dominance and pure base class Matthias C++ 2 12-10-2005 03:12 AM
accessing base class in multiple inheritance Robert Swan C++ 2 11-30-2004 10:07 PM
Multiple inheritance with a common base class Markus Bertheau Python 0 08-10-2004 11:37 AM
Delete a class with multiple inheritance through base pointer? Ian C++ 7 02-12-2004 11:23 AM
Overiding a virtual function of multiple inheritance base class Ronnie C++ 4 11-19-2003 06:46 AM



Advertisments