Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Multiple Inheritance in Python

Give Feedback

Python supports inheritance from multiple classes. In this lesson, you’ll see:

  • How multiple inheritance works
  • How to use super() to call methods inherited from multiple parents
  • What complexities derive from multiple inheritance
  • How to write a mixin, which is a common use of multiple inheritance

A class can inherit from multiple parents. For example, you could build a class representing a 3D shape by inheriting from two 2D shapes:

class RightPyramid(Triangle, Square):
    def __init__(self, base, slant_height):
        self.base = base
        self.slant_height = slant_height

    def what_am_i(self):
        return 'RightPyramid'

The Method Resolution Order (MRO) determines where Python looks for a method when there is a hierarchy of classes. Using super() accesses the next class in the MRO:

class A:
    def __init__(self):
        print('A')
        super().__init__()

class B(A):
    def __init__(self):
        print('B')
        super().__init__()

class X:
    def __init__(self):
        print('X')
        super().__init__()

class Forward(B, X):
    def __init__(self):
        print('Forward')
        super().__init__()

class Backward(X, B):
    def __init__(self):
        print('Backward')
        super().__init__()

If you combine the MRO and the **kwargs feature for specifying name-value pairs during construction, you can write code that passes parameters to parent classes even if they have different names:

class Rectangle:
    def __init__(self, length, width, **kwargs):
        self.length = length
        self.width = width
        super().__init__(**kwargs)

    def area(self):
        return self.length * self.width

    def perimeter(self):
        return 2 * self.length + 2 * self.width

class Square(Rectangle):
    def __init__(self, length, **kwargs):
        super().__init__(length=length, width=length, **kwargs)

class Triangle:
    def __init__(self, base, height, **kwargs):
        self.base = base
        self.height = height
        super().__init__(**kwargs)

    def tri_area(self):
        return 0.5 * self.base * self.height

class RightPyramid(Square, Triangle):
    def __init__(self, base, slant_height, **kwargs):
        self.base = base
        self.slant_height = slant_height
        kwargs["height"] = slant_height
        kwargs["length"] = base
        super().__init__(base=base, **kwargs)

    def area(self):
        base_area = super().area()
        perimeter = super().perimeter()
        return 0.5 * perimeter * self.slant_height + base_area

    def area_2(self):
        base_area = super().area()
        triangle_area = super().tri_area()
        return triangle_area * 4 + base_area

Multiple inheritance can get tricky quickly. A simple use case that is common in the field is to write a mixin. A mixin is a class that doesn’t care about its position in the hierarchy, but just provides one or more convenience methods:

class SurfaceAreaMixin:
    def surface_area(self):
        surface_area = 0
        for surface in self.surfaces:
            surface_area += surface.area(self)

        return surface_area

class Cube(Square, SurfaceAreaMixin):
    def __init__(self, length):
        super().__init__(length)
        self.surfaces = [Square, Square, Square, Square, Square, Square]

class RightPyramid(Square, Triangle, SurfaceAreaMixin):
    def __init__(self, base, slant_height):
        self.base = base
        self.slant_height = slant_height
        self.height = slant_height
        self.length = base
        self.width = base

        self.surfaces = [Square, Triangle, Triangle, Triangle, Triangle]

Here’s what you get:

>>>
>>> cube = Cube(3)
>>> cube.surface_area()
54

Download

Course Slides (PDF)

896.4 KB

Comments & Discussion

Anonymous on Jan. 14, 2020

Superbly motivated, organized, and paced. Most appreciated

Alex on Jan. 14, 2020

Thank you,especially for the Mixins example.

Anonymous on Jan. 16, 2020

Yea, I have read the documentation multiple times, but the way this was presented made it extremely digestible and clear - very well put together. Now to watch it 5 more times.

rhuang on Jan. 30, 2020

Great tutorial! Thanks!

ajp4 on Feb. 2, 2020

Best explanation I have seen. Thank you!

SkyFox on March 27, 2020

I came to this tutorial to understand to concept of Mixins. I really happy I got everything in less than 30 minutes. Really appreciate such explanation simplicity!

Anonymous on April 4, 2020

I liked the explanation of the “why” in creating Mix-ins and the potential pitfalls of multiple-inheritance. I love the explanations simplicity and your measured vocal speed. Keep up the Good Work!!

Erikton Konomi on April 12, 2020

Fantastic tutorial! I really enjoyed how concise and to the point all three videos were, with solid examples. The introduction of the mixin pattern however made all the difference in the end. I’ll be decoupling some code at work pretty soon with this :) Thanks!

ricardoaparicio92 on April 18, 2020

I’m lost!

Ricky White RP Team on April 19, 2020

@richardoaparicio92 What are you struggling with?

Liz Schley on April 28, 2020

This is great, so thank you! My purpose was to understand how OOP works in Python, so that I am capable of designing good code when I need to.

Liz Schley on April 28, 2020

My favorite thing was the mro method and using mixins to prevent confusion. Definitely my plan, if possible since confusing code creates bugs that are time-consuming to fix.

graham17 on May 18, 2020

Really useful - a few pennies dropped right here. The only thing I didn’t get was the final cube = SACube(3) I suspect this was an error - I couldn’t find any ref to class SACube anywhere - but maybe I missed it - overall - a great concise tutorial

Christopher Trudeau RP Team on May 19, 2020

Hi graham17,

Good catch. That’s an artifact from an earlier version of the code. We’ll fix it shortly. Thanks for letting us know. …ct

Become a Member to join the conversation.