osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Class initialization with multiple inheritance



> On 16 Jul 2019, at 01:13, Joseph L. Casale <jcasale at activenetwerx.com> wrote:
> 
> I am trying to find explicit documentation on the initialization logic for a
> Base class when multiple exist. For the example in the documentation at
> https://docs.python.org/3/tutorial/classes.html#multiple-inheritance,
> if Base1 and Base2 both themselves inherited from the same base class,
> only Base1 would call __init__ on the subclass, Base2 would not. While
> I know this from experience, I need to locate actual documentation, does
> Anyone know if it exists?

The docs are not clear on this.

If you are using super().__init__() in all classes then the key to only calling __init__
once is that super() uses the MRO to find the next class's __init__ to call.

The MRO algorithm takes any hierarchy of inheritance and turns it into a
predictable ordered list of the classes. The __mro__ attribute allows you to see this.

For example (m.py):

class CommonBase(object):
    def __init__( self ):
        print( 'CommonBase.__init__()' )
        super().__init__()

class Left(CommonBase):
    def __init__( self ):
        print( 'Left.__init__()' )
        super().__init__()

class Right(CommonBase):
    def __init__( self ):
        print( 'Right.__init__()' )
        super().__init__()

class LeftAndRight(Left, Right):
    def __init__( self ):
        print( 'LeftAndRight.__init__()' )
        super().__init__()


instance = LeftAndRight()

Outputs:

LeftAndRight.__init__()
Left.__init__()
Right.__init__()
CommonBase.__init__()

And here is the MRO for LeftAndRight.

>>> import m
LeftAndRight.__init__()
Left.__init__()
Right.__init__()
CommonBase.__init__()
>>> m.LeftAndRight.__mro__
(<class 'm.LeftAndRight'>,
 <class 'm.Left'>,
 <class 'm.Right'>,
 <class 'm.CommonBase'>,
 <class 'object'>)
>>>

Notice that I explicitly derived from object that is the default.
But here you see that class object is always there even if I omit it.

>>> class Foo:
...     pass
...
>>> Foo.__mro__
(<class '__main__.Foo'>, <class 'object'>)

Barry


> 
> Thanks,
> jlc
> 
> -- 
> https://mail.python.org/mailman/listinfo/python-list
>