Python Inheritance & Operator Overloading: OOP Masterclass

Introduction to Inheritance
Inheritance is one of the pillars of Object-Oriented Programming (OOP). Much like biological inheritance, it allows a "child" class to take on the attributes and methods of a "parent" class. This promotes code reusability and helps you follow the DRY (Don't Repeat Yourself) principle.
In Python, every class you create automatically inherits from the built-in object class, giving it basic functionality.
1class Parent:
2 def speak(self):
3 print("Parent speaking")
4
5class Child(Parent):
6 def play(self):
7 print("Child playing")
8
9c = Child()
10c.speak() # Inherited method
11c.play() # Own methodTypes of Inheritance in Python
Python is incredibly flexible and supports several inheritance patterns:
1. Simple Inheritance
A single child class inherits from a single parent class.
Example: Class B(A)
2. Multiple Inheritance
A child class inherits from more than one parent class. This is a powerful feature where Python uses MRO (Method Resolution Order) to decide which method to call if both parents have the same one.
Example: Class C(A, B)
3. Multilevel Inheritance
A child class inherits from a parent, which in turn inherits from another class.
Example: Class C(B) where Class B(A)
4. Hierarchical Inheritance
Multiple child classes inherit from the same parent.
Example: Class B(A) and Class C(A)
5. Hybrid Inheritance
A combination of two or more of the above types.
Method Resolution Order (MRO)
When dealing with Multiple Inheritance, Python needs a way to decide which class to look in first. This is called MRO.
Modern Python uses the C3 Linearization Algorithm (or simply the "New Style MRO") to create a consistent search path. You can check the MRO of any class using the .mro() method.
1class A: pass
2class B(A): pass
3class C(A): pass
4class D(B, C): pass
5
6print(D.mro())
7# Output: [D, B, C, A, object]Pro Tip: C3 Linearization
Python's MRO is designed to be monotonic, meaning it respects the order of inheritance you define and ensures a class is always searched after its children.
Operator Overloading
Operator Overloading allows you to define how standard operators (like +, -, *) behave when used with your custom objects. This makes your classes feel like built-in Python types.
Python implements this using Dunder (Double Under) Methods.
Common Overloading Methods
| Operator | Dunder Method | Purpose |
|---|---|---|
+ | __add__(self, other) | Addition |
- | __sub__(self, other) | Subtraction |
* | __mul__(self, other) | Multiplication |
/ | __truediv__(self, other) | Division |
== | __eq__(self, other) | Equality |
< | __lt__(self, other) | Less Than |
** | __pow__(self, other) | Power |
Example: Overloading Multiplication
Let's create a Point class where the * operator calculates the cross product (or simple coordinate multiplication).
1class Point:
2 def __init__(self, x, y):
3 self.x = x
4 self.y = y
5
6 def __mul__(self, other):
7 # Custom logic for multiplication
8 return (self.x * other.x) + (self.y * other.y)
9
10p1 = Point(2, 3)
11p2 = Point(4, 5)
12
13print(p1 * p2) # Output: 23 (2*4 + 3*5)Conclusion
Inheritance and Operator Overloading are advanced tools that allow you to create elegant, powerful, and intuitive software architectures. By mastering these, you can write Python code that is both highly reusable and extremely readable.
What's Next?
Now that you've mastered OOP concepts, explore Python Decorators to learn how to modify function behavior dynamically!
