Python · object-oriented programming

Inheritance

A class can build on another: it gets the parent's methods and attributes, and can override or extend them.

How Python finds a method

Start at the object's class

For dog.speak(), Python first looks in Dog.

Climb to the parents

Not there? It tries the parent class, then its parent, up to object.

First match wins

This search order is the method resolution order (MRO). Watch the pink probe climb the diagrams.

Basic inheritance


          # base class
          class Animal:
              def speak(self):
                  return "Some sound"

          # derived class
          class Dog(Animal):
              def speak(self):
                  return "Woof!"

          Dog().speak()
          # ans: "Woof!"
        

Inheriting attributes


          # inherit __init__
          class Animal:
              def __init__(self, name):
                  self.name = name

          class Dog(Animal):
              pass

          Dog("Rex").name
          # ans: "Rex"
        

Dog has no __init__ of its own, so Animal's runs.

Using super()


          # call parent __init__
          class Animal:
              def __init__(self, name):
                  self.name = name

          class Dog(Animal):
              def __init__(self, name, breed):
                  super().__init__(name)
                  self.breed = breed

          Dog("Rex", "Lab").name
          # ans: "Rex"
        

super() continues the search in the parent, so both __init__ methods run.

Override methods


          # override parent method
          class Animal:
              def speak(self):
                  return "Sound"

          class Dog(Animal):
              def speak(self):
                  return "Woof!"

          Dog().speak()
          # ans: "Woof!"
        

The search stops at Dog; Animal.speak is never reached.

Call the parent method


          # call parent from child
          class Animal:
              def speak(self):
                  return "Sound"

          class Dog(Animal):
              def speak(self):
                  parent = super().speak()
                  return f"{parent} and Woof!"

          Dog().speak()
          # ans: "Sound and Woof!"
        

Exercises

Predict the answer, then press → to follow the lookup.

Exercise 1


          # isinstance with inheritance?
          class Animal:
              pass
          class Dog(Animal):
              pass

          dog = Dog()
          isinstance(dog, Animal)
          # ans: True
        

Exercise 2


          # issubclass?
          class Animal:
              pass
          class Dog(Animal):
              pass

          issubclass(Dog, Animal)
          # ans: True
        

Exercise 3


          # method resolution order?
          class Animal:
              def speak(self):
                  return "A"
          class Dog(Animal):
              pass

          Dog().speak()
          # ans: "A" (inherited)
        

Exercise 4


          # super() without override?
          class Base:
              def method(self):
                  return 1
          class Derived(Base):
              def other(self):
                  return super().method()

          Derived().other()
          # ans: 1
        

Exercise 5


          # multiple inheritance?
          class A:
              def method(self):
                  return "A"
          class B:
              def method(self):
                  return "B"
          class C(A, B):
              pass

          C().method()
          # ans: "A" (parents are searched left to right)
        

Exercise 6


          # __mro__?
          class Animal:
              pass
          class Dog(Animal):
              pass

          Dog.__mro__
          # ans: (Dog, Animal, object)
        

Exercise 7


          # override __init__ without super?
          class Base:
              def __init__(self):
                  self.x = 1
          class Derived(Base):
              def __init__(self):
                  self.y = 2

          Derived().x
          # ans: AttributeError (no super call)
        

Exercise 8


          # call grandparent?
          class A:
              def method(self):
                  return "A"
          class B(A):
              def method(self):
                  return "B"
          class C(B):
              def method(self):
                  return super(B, self).method()

          C().method()
          # ans: "A"
        

super(B, self) starts the search after B in the MRO.

Exercise 9


          # inherit from object?
          class MyClass:
              pass
          # ans: implicitly inherits from object

          isinstance(MyClass(), object)
          # ans: True
        

Exercise 10


          # diamond problem?
          class A:
              def method(self):
                  return "A"
          class B(A):
              pass
          class C(A):
              pass
          class D(B, C):
              pass

          D().method()
          # ans: "A" (MRO: D, B, C, A, object)
        

Python visits B and C before their shared parent A, so A is checked only once.

Remember

class Child(Parent)

The child gets everything the parent has.

Override

Define a method with the same name to replace the parent's.

super()

Calls the next class in the MRO; use it so parent __init__s still run.

MRO

The lookup order: the class, then its parents left to right, ending at object.