Author: Amin Boulouma, Software Engineer Github source code: https://github.com/aminblm/ai_systems_design_from_scratch Engineering Blog: https://aminblm.github.io/ai_systems_design_from_scratch/blog/
7 Reasons You Should Abandon Manual Methods for Dunder Magic
Ever wondered how Python knows to add two numbers with + or how len() calculates the size of a list? The answer lies in Dunder Methods (Double Under). These special methods provide the interface between your custom objects and Python’s built-in syntax. If you are still writing manual object.get_value() methods instead of leveraging dunder magic, you are ignoring the most powerful tool in the language’s arsenal.
The Core Concept
A Dunder Method is a method that begins and ends with double underscores (e.g., __init__, __str__). These methods are not intended to be called directly by you; they are “hooks” that the Python interpreter calls automatically when a specific operation is performed on your object.
Glossary for Beginners
- Dunder: Short for “Double Under,” referring to the
__prefix and suffix. - Operator Overloading: The ability to redefine how standard operators (like
+,-,==) behave when used with your objects. - Dunder Hook: A specific dunder method triggered by a language operation (e.g.,
__len__is triggered by thelen()function). - Magic Methods: Another term for dunder methods, highlighting their automatic invocation by the interpreter.
Why We Choose Dunder Methods Over Manual Wrappers
We choose dunder methods to achieve Syntactic Sugar. By implementing standard interfaces, our classes become drop-in replacements for standard types. This allows our internal modules to communicate using idiomatic Python syntax rather than custom, project-specific API calls.
Why X over Y? We choose __add__ over object.add_to_total() because it allows our objects to participate in standard mathematical expressions. This reduces the cognitive load for developers using our libraries, as the usage pattern matches their existing knowledge of Python’s built-in types.
Implementation: The Dunder Pattern
Simple Example: String Representation
class User:
def __init__(self, name: str):
self.name = name
def __str__(self) -> str:
return f"User(name={self.name})"
user = User("Amin")
print(user) # Output: User(name=Amin)
Complex Example: Production-Grade Operator Overloading
In production, we often implement custom comparison or arithmetic logic to make our data models behave intuitively.
from dataclasses import dataclass
@dataclass
class Money:
amount: float
currency: str
def __add__(self, other):
if self.currency != other.currency:
raise ValueError("Currency mismatch")
return Money(self.amount + other.amount, self.currency)
def __eq__(self, other):
return self.amount == other.amount and self.currency == other.currency
# Usage
wallet_a = Money(100, "USD")
wallet_b = Money(50, "USD")
total = wallet_a + wallet_b
print(total) # Output: Money(amount=150.0, currency='USD')
Quick Reference: Common Dunder Hooks
| Operation | Dunder Method | Purpose |
|---|---|---|
| Instantiation | __init__ |
Object setup |
| Representation | __str__ |
User-friendly string display |
| Comparison | __eq__ |
Equality logic |
| Size | __len__ |
Object length |
| Addition | __add__ |
Math operators |
Developer Checklist
- Have you implemented
__repr__for clear debugging and__str__for user-facing output? - Is your
__eq__implementation logically complete? (Remember: if you define__eq__, consider defining__hash__if the object is to be used in sets/dicts). - Are you overusing dunder methods? (Only implement them if they provide clear utility to the user).
- Does your class act like a collection? Consider
__getitem__and__iter__.
TL;DR Summary
Stop writing custom methods for standard object lifecycle and comparison tasks. Dunder Methods are the hooks that make your code feel like a native Python object. By implementing them, you slash the amount of boilerplate code required to interact with your data and ensure your libraries are intuitive for every Python engineer. Always provide a clear __repr__ for production debugging!