Magic methods (also known as dunder methods, short for double underscore) in Python are special methods that have double underscores before and after their names, like __init__, __str__, __add__, etc.
They are not magical in the supernatural sense but give your objects the power to interact with built-in Python features like operators, functions, and even loops!
✨ Why use magic methods?
Magic methods allow your custom objects to behave like built-in types (int, str, list, etc.). This means you can:
- Initialize objects (
__init__) - Use operators like
+,-,<(__add__,__lt__) - Represent objects as strings (
__str__,__repr__) - Get length using
len()(__len__) - Access items like dictionaries/lists (
__getitem__,__setitem__) - Use loops (
__iter__,__next__) - Compare objects (
__eq__,__lt__, etc.)
🔧 Common Magic Methods and Their Uses
| Magic Method | Purpose | Example |
|---|---|---|
__init__ | Constructor | Person("Himanshu") |
__str__ | User-friendly string | print(obj) |
__repr__ | Official string (for debugging) | repr(obj) |
__len__ | Length of object | len(obj) |
__getitem__ | Access elements | obj |
__setitem__ | Set elements | obj = value |
__delitem__ | Delete elements | del obj |
__iter__ | Make object iterable | for x in obj: |
__next__ | Next element in iteration | next(obj) |
__add__ | Add two objects | obj1 + obj2 |
__sub__ | Subtract objects | obj1 - obj2 |
__eq__ | Equality check | obj1 == obj2 |
__lt__ | Less than check | obj1 < obj2 |
__call__ | Make object callable like a function | obj() |
__contains__ | Membership test (in) | "x" in obj |
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"Point({self.x}, {self.y})"
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
# Example usage
p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1) # Output: Point(1, 2)
print(p2) # Output: Point(3, 4)
p3 = p1 + p2
print(p3) # Output: Point(4, 6)
print(p1 == p2) # Output: False
print(p1 == Point(1, 2)) # Output: True
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"Person({self.name}, {self.age})" # User-friendly
def __repr__(self):
return f"Person(name='{self.name}', age={self.age})" # Unambiguous, for debugging
p = Person("Alice", 30)
print(str(p)) # Person(Alice, 30)
print(repr(p)) # Person(name='Alice', age=30)
print(p) # Person(Alice, 30)
🧠 Tips
- Not all magic methods are required — use only those that make sense for your object.
__str__is for humans,__repr__is for developers.