Inheritance, Polymorphism, super() & MRO
Inheritance allows classes to share behaviors and establish clean polymorphic domain models. Unlike single-inheritance languages like Java and C#, Python natively supports multiple inheritance. Learn how super() navigates class hierarchies, how the C3 Linearization (MRO) algorithm prevents the Diamond Problem, and how to define formal interface contracts with Abstract Base Classes (ABCs).
1. Single Inheritance & super() Initialization
A subclass inherits attributes and methods from its parent. Calling super().__init__() delegates initialization up the inheritance tree without explicitly naming the parent class:
class Employee:
def __init__(self, name: str, employee_id: str, base_salary: float):
self.name = name
self.employee_id = employee_id
self.base_salary = base_salary
def calculate_annual_compensation(self) -> float:
return self.base_salary
class SoftwareEngineer(Employee):
def __init__(self, name: str, employee_id: str, base_salary: float, equity_bonus: float):
# Call parent constructor via super()
super().__init__(name, employee_id, base_salary)
self.equity_bonus = equity_bonus
# Override parent method (Polymorphism)
def calculate_annual_compensation(self) -> float:
return super().calculate_annual_compensation() + self.equity_bonus
eng = SoftwareEngineer("Alice", "SE-402", 145000.0, 35000.0)
print(f"Annual compensation for {eng.name}: $${eng.calculate_annual_compensation():,.2f}")2. Multiple Inheritance & The Diamond Problem Solved
The "Diamond Problem" occurs when class D inherits from both B and C, and both B and C inherit from base class A. Which version of a shared method does D execute?
Python resolves this deterministically using the C3 Linearization Algorithm, producing theMethod Resolution Order (MRO). You can inspect any class's exact lookup order with Class.__mro__:
class A:
def execute(self):
print("Executing in Class A")
class B(A):
def execute(self):
print("Executing in Class B")
super().execute()
class C(A):
def execute(self):
print("Executing in Class C")
super().execute()
class D(B, C):
def execute(self):
print("Executing in Class D")
super().execute()
d = D()
d.execute()
# Inspect the exact C3 Linearization order:
print("\nMRO Lookup Chain:")
for cls in D.__mro__:
print(" ->", cls.__name__)
# Order: D -> B -> C -> A -> object3. Enforcing Interfaces with Abstract Base Classes (abc.ABC)
In large enterprise architectures, you want to define strict interface contracts that subclassesmust implement. If a subclass forgets to implement an @abstractmethod, Python refuses to instantiate it at runtime!
from abc import ABC, abstractmethod
class BaseDatabaseConnector(ABC):
"""Abstract interface for all enterprise database adapters."""
@abstractmethod
def connect(self) -> None:
"""Establish network connection to database cluster."""
pass
@abstractmethod
def execute_query(self, query: str) -> list[dict]:
"""Execute SQL query and return records."""
pass
class PostgreSQLConnector(BaseDatabaseConnector):
def connect(self) -> None:
print("Connected to PostgreSQL on port 5432.")
def execute_query(self, query: str) -> list[dict]:
return [{"id": 1, "status": "ACTIVE"}]
# If a subclass forgets execute_query(), instantiating it raises TypeError:
# TypeError: Can't instantiate abstract class IncompleteConnector with abstract method execute_query
pg = PostgreSQLConnector()
pg.connect()Explore Related Tools
Hand-picked utilities and calculators related to this tool.
