A class can build on another: it gets the parent's methods and attributes, and can override or extend them.
For dog.speak(), Python first looks in Dog.
Not there? It tries the parent class, then its parent, up to object.
This search order is the method resolution order (MRO). Watch the pink probe climb the diagrams.
# base class
class Animal:
def speak(self):
return "Some sound"
# derived class
class Dog(Animal):
def speak(self):
return "Woof!"
Dog().speak()
# ans: "Woof!"
# 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.
# 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 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 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!"
Predict the answer, then press → to follow the lookup.
# isinstance with inheritance?
class Animal:
pass
class Dog(Animal):
pass
dog = Dog()
isinstance(dog, Animal)
# ans: True
# issubclass?
class Animal:
pass
class Dog(Animal):
pass
issubclass(Dog, Animal)
# ans: True
# method resolution order?
class Animal:
def speak(self):
return "A"
class Dog(Animal):
pass
Dog().speak()
# ans: "A" (inherited)
# super() without override?
class Base:
def method(self):
return 1
class Derived(Base):
def other(self):
return super().method()
Derived().other()
# ans: 1
# 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)
# __mro__?
class Animal:
pass
class Dog(Animal):
pass
Dog.__mro__
# ans: (Dog, Animal, object)
# 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)
# 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.
# inherit from object?
class MyClass:
pass
# ans: implicitly inherits from object
isinstance(MyClass(), object)
# ans: True
# 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.
class Child(Parent)The child gets everything the parent has.
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.
The lookup order: the class, then its parents left to right, ending at object.