Advanced OOP
Python’s Hidden Spells
Imagine you’re a hacker who discovers secret commands in your toolkit like hidden spells that let you bend reality. In Python, these are called magic methods (also known as dunder methods, because they start and end with __). They allow you to customize how objects behave with built‑in operations like +, ==, or even print().
With operator overloading, you can redefine how operators work for your own classes. Suddenly, your objects can add, compare, or display themselves in ways that feel natural. This chapter is about learning how to wield these hidden spells to make your classes more powerful and intuitive.
Why Magic Methods Matter
- Magic Methods: Special methods with double underscores (
__init__,__str__,__add__, etc.) that Python calls automatically. - Operator Overloading: Redefining operators (
+,-,*,==) for custom classes. - Customization: Lets objects behave like built‑in types.
- Readability: Makes code more intuitive and objects interact naturally with operators.
- Real‑World Analogy: Think of customizing a universal remote. The same button (
+) can increase volume on a TV or brightness on a monitor, depending on the device.
Common Magic Methods
- Called when an object is created.
- Defines how the object is displayed when printed.
- Customizes
==operator.
__eq__ – Equality Check
class Hacker:
def __init__(self, name):
self.name = name
def __eq__(self, other):
return self.name == other.name
print(Hacker("Shubham") == Hacker("Shubham")) # True
__str__ – String Representation
class Hacker:
def __init__(self, name):
self.name = name
def __str__(self):
return f"Hacker: {self.name}"
print(Hacker("Shubham"))
__init__ – Constructor
class Hacker:
def __init__(self, name):
self.name = name
h = Hacker("Shubham")
Operator Overloading
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f"({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(4, 5)
print(v1 + v2) # (6, 8)
- Why? The
+operator now works naturally withVectorobjects.
More Magic Methods
__call__: Makes objects callable like functions
class Greeter:
def __call__(self, name):
print(f"Hello, {name}!")
g = Greeter()
g("Shubham") # Hello, Shubham!
__getitem__: Defines indexing behavior
class Team:
def __init__(self, members):
self.members = members
def __getitem__(self, index):
return self.members[index]
team = Team(["Shubham", "Aditi"])
print(team[0]) # Shubham
__len__: Defines behavior for len()
class Team:
def __init__(self, members):
self.members = members
def __len__(self):
return len(self.members)
print(len(Team(["Shubham", "Aditi"]))) # 2
Real‑World Example
class Account:
def __init__(self, balance):
self.balance = balance
def __add__(self, other):
return Account(self.balance + other.balance)
def __str__(self):
return f"Balance: {self.balance}"
acc1 = Account(1000)
acc2 = Account(500)
print(acc1 + acc2) # Balance: 1500
- Why? Operator overloading makes accounts behave naturally when combined.
The Hacker’s Notebook
- Magic methods are Python’s special hooks that customize object behavior. Operator overloading lets objects interact naturally with
+,==,len(), and more. - Methods like
__str__,__eq__, and__add__make classes feel like built‑in types. Overloading improves readability and usability, turning custom objects into intuitive tools.
Hacker’s Mindset: treat magic methods as secret codes. With them, you bend Python’s rules to make your objects smarter, cleaner, and more powerful.
