Can a python class inherit from multiple classes?

Overall

Assuming everything descends from object (you are on your own if it doesn't), Python computes a method resolution order (MRO) based on your class inheritance tree. The MRO satisfies 3 properties:

  • Children of a class come before their parents
  • Left parents come before right parents
  • A class only appears once in the MRO

If no such ordering exists, Python errors. The inner workings of this is a C3 Linerization of the classes ancestry. Read all about it here: https://www.python.org/download/releases/2.3/mro/

Thus, in both of the examples below, it is:

  1. Child
  2. Left
  3. Right
  4. Parent

When a method is called, the first occurrence of that method in the MRO is the one that is called. Any class that doesn't implement that method is skipped. Any call to super within that method will call the next occurrence of that method in the MRO. Consequently, it matters both what order you place classes in inheritance, and where you put the calls to super in the methods.

Note that you can see the MRO in python by using the __mro__ method. Child.__mro__ in any of the examples below returns:

(__main__.Child, __main__.Left, __main__.Right, __main__.Parent, object)

Examples

All of the following examples have a diamond inheritance of classes like so:

    Parent
    /   \
   /     \
Left    Right
   \     /
    \   /
    Child

With super first in each method

class Parent(object):
    def __init__(self):
        super(Parent, self).__init__()
        print("parent")

class Left(Parent):
    def __init__(self):
        super(Left, self).__init__()
        print("left")

class Right(Parent):
    def __init__(self):
        super(Right, self).__init__()
        print("right")

class Child(Left, Right):
    def __init__(self):
        super(Child, self).__init__()
        print("child")

Child() outputs:

parent
right
left
child
    

With super last in each method

class Parent(object):
    def __init__(self):
        print("parent")
        super(Parent, self).__init__()

class Left(Parent):
    def __init__(self):
        print("left")
        super(Left, self).__init__()

class Right(Parent):
    def __init__(self):
        print("right")
        super(Right, self).__init__()

class Child(Left, Right):
    def __init__(self):
        print("child")
        super(Child, self).__init__()

Child() outputs:

child
left
right
parent

When not all classes call super

Inheritance order matters most if not all classes in the chain of inheritance call super. For example, if Left doesn't call super, then the method on Right and Parent are never called:

class Parent(object):
    def __init__(self):
        print("parent")
        super(Parent, self).__init__()

class Left(Parent):
    def __init__(self):
        print("left")

class Right(Parent):
    def __init__(self):
        print("right")
        super(Right, self).__init__()

class Child(Left, Right):
    def __init__(self):
        print("child")
        super(Child, self).__init__()

Child() outputs:

child
left

Alternatively, if Right doesn't call super, Parent is still skipped:

class Parent(object):
    def __init__(self):
        print("parent")
        super(Parent, self).__init__()

class Left(Parent):
    def __init__(self):
        print("left")
        super(Left, self).__init__()

class Right(Parent):
    def __init__(self):
        print("right")

class Child(Left, Right):
    def __init__(self):
        print("child")
        super(Child, self).__init__()

Here, Child() outputs:

child
left
right

Calling a method on a particular parent

If you want to access the method of a particular parent class, you should reference that class directly rather than using super. Super is about following the chain of inheritance, not getting to a specific class's method.

Here's how to reference a particular parent's method:

class Parent(object):
    def __init__(self):
        super(Parent, self).__init__()
        print("parent")

class Left(Parent):
    def __init__(self):
        super(Left, self).__init__()
        print("left")

class Right(Parent):
    def __init__(self):
        super(Right, self).__init__()
        print("right")

class Child(Left, Right):
    def __init__(self):
        Parent.__init__(self)
        print("child")

In this case, Child() outputs:

parent
child

Can a class be inherited from multiple classes?

Multiple Inheritance is a feature of C++ where a class can inherit from more than one classes. The constructors of inherited classes are called in the same order in which they are inherited. For example, in the following program, B's constructor is called before A's constructor.

How many classes can Python inherit from?

Python allows you to inherit from two different classes by specifying them between parenthesis in the class declaration.

How many classes can a Python class inherit at most?

Since the Child class is derived from two classes, it inherits features from both classes. Of course, you can inherit from more than two classes. Theoretically, there is no limit to the number of classes you can use to construct a child class.

Is it possible multiple inheritance in Python?

Yes, Python supports multiple inheritance. Like C++, a class can be derived from more than one base classes in Python. This is called Multiple Inheritance.

Tải thêm tài liệu liên quan đến bài viết Can a python class inherit from multiple classes?