Re: Multiple inheritance with a common base class

Discussion in 'Python' started by Markus Bertheau, Aug 10, 2004.

  1. В Втр, 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 <>
     
    Markus Bertheau, Aug 10, 2004
    #1
    1. Advertising

  2. Markus Bertheau

    Duncan Booth Guest

    Markus Bertheau <> wrote in
    news::

    > 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.
     
    Duncan Booth, Aug 10, 2004
    #2
    1. Advertising

  3. Markus Bertheau

    Peter Otten Guest

    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
     
    Peter Otten, Aug 10, 2004
    #3
  4. В Втр, 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 <>
     
    Markus Bertheau, Aug 10, 2004
    #4
  5. super and __init__ arguments (Was: Re: Multiple inheritance with acommon base class)

    В Втр, 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 <>
     
    Markus Bertheau, Aug 10, 2004
    #5
  6. Markus Bertheau

    Duncan Booth Guest

    Re: super and __init__ arguments (Was: Re: Multiple inheritance with a common base class)

    Markus Bertheau <> wrote in
    news::

    > 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)
     
    Duncan Booth, Aug 10, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ronnie
    Replies:
    4
    Views:
    433
    Ronnie
    Nov 19, 2003
  2. Ian
    Replies:
    7
    Views:
    4,454
    Chris Theis
    Feb 12, 2004
  3. Robert Swan
    Replies:
    2
    Views:
    382
    Greg Schmidt
    Nov 30, 2004
  4. Markus Bertheau

    Multiple inheritance with a common base class

    Markus Bertheau, Aug 10, 2004, in forum: Python
    Replies:
    0
    Views:
    317
    Markus Bertheau
    Aug 10, 2004
  5. Matthias
    Replies:
    2
    Views:
    346
    Victor Bazarov
    Dec 10, 2005
Loading...

Share This Page