1. Introduction
Magic methods (also called dunder methods, short for 'double underscore') are special methods surrounded by double underscores, such as __init__, __str__, and __add__. Python calls them automatically in response to built-in operations and syntax — you rarely call them directly. They are the mechanism that lets a custom class behave like a built-in type: support printing, equality checks, iteration, indexing, arithmetic, and more.
Cricket analogy: A custom Player class defining __add__ lets you write player1 + player2 to combine their stats automatically, just as Python calls __init__ behind the scenes the moment you draft a new player object.
Because dunder methods are invoked implicitly by the interpreter (e.g. print(obj) triggers __str__, obj1 == obj2 triggers __eq__), they are the primary way Python implements 'protocols' — informal interfaces that objects opt into by defining the right set of methods. This is the foundation of Python's data model.
Cricket analogy: print(player) silently triggering __str__ is like a scoreboard operator automatically formatting a player's name for display without being explicitly told how -- dunder methods are Python's version of an agreed-upon protocol.
2. Syntax
class MyClass:
def __init__(self, value):
self.value = value
def __repr__(self):
# Unambiguous, developer-facing representation
return f"MyClass({self.value!r})"
def __str__(self):
# Readable, user-facing representation
return f"MyClass with value {self.value}"
def __eq__(self, other):
if not isinstance(other, MyClass):
return NotImplemented
return self.value == other.value
def __hash__(self):
return hash(self.value)
def __len__(self):
return len(str(self.value))3. Explanation
Common dunder methods fall into families: object creation (__init__, __new__), string representation (__str__, __repr__), comparison (__eq__, __lt__, __le__, ...), container behavior (__len__, __getitem__, __setitem__, __contains__), numeric operators (__add__, __sub__, __mul__), and context managers (__enter__, __exit__). Python looks these up on the class, not the instance, so overriding them on the class is what changes built-in behavior.
Cricket analogy: __init__ drafts a new Player, __str__/__repr__ format how they're announced, __eq__/__lt__ rank them by average, __len__/__getitem__ let you index a Team's squad, and __add__ combines stats -- all defined on the Player class, not on any one instance.
__str__ vs __repr__: __repr__ should return an unambiguous string that (ideally) could recreate the object, and is used by repr(), the interactive shell, and inside containers (e.g. printing a list of objects). __str__ is used by str() and print() for a human-friendly display. If __str__ is not defined, Python falls back to __repr__. Always define __repr__ at minimum; add __str__ only when a different, friendlier display is useful.
Gotcha: overriding __eq__ without also overriding __hash__ makes instances unhashable. Python's default __hash__ is based on identity (id()), which is inconsistent with a custom __eq__ that compares values. To prevent silently-broken hashing, Python sets __hash__ to None automatically when you define __eq__ but not __hash__ — instances then raise TypeError('unhashable type') if you try to put them in a set or use them as dict keys. Define __hash__ explicitly (usually hash of the same fields used in __eq__) whenever you override __eq__ and still need the object to be hashable.
4. Example
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
def __str__(self):
return f"({self.x}, {self.y})"
def __eq__(self, other):
if not isinstance(other, Point):
return NotImplemented
return (self.x, self.y) == (other.x, other.y)
def __hash__(self):
return hash((self.x, self.y))
def __len__(self):
return int((self.x ** 2 + self.y ** 2) ** 0.5)
p1 = Point(3, 4)
p2 = Point(3, 4)
p3 = Point(1, 1)
print(p1)
print(repr(p1))
print(p1 == p2)
print(p1 == p3)
print(len(p1))
print(len({p1, p2, p3}))5. Output
(3, 4)
Point(3, 4)
True
False
5
26. Key Takeaways
- Dunder methods let custom objects integrate with built-in syntax like print(), ==, len(), and for loops.
- __repr__ is for developers/debugging; __str__ is for end-user display; __str__ falls back to __repr__ if undefined.
- Overriding __eq__ without __hash__ makes an object unhashable — define both together for value-based equality.
- Comparison and arithmetic dunder methods should return NotImplemented (not raise) when the other operand's type isn't supported.
- Python calls dunder methods implicitly; you almost never call obj.__str__() directly — use str(obj) instead.
- set() and dict deduplication/lookup rely on both __eq__ and __hash__ being consistent with each other.
Practice what you learned
1. What happens if a class defines __eq__ but does not define __hash__?
2. Which magic method is used by print(obj) if both __str__ and __repr__ are defined?
3. What should a custom __add__ method return when the other operand's type is unsupported?
4. Given class Point with __str__ returning '(x, y)' and __repr__ returning 'Point(x, y)', what does repr(p1) print for Point(3, 4)?
5. Which dunder method makes len(obj) work on a custom class?
6. Why must objects in a Python set be hashable and have consistent __eq__/__hash__?
Was this page helpful?
You May Also Like
Class Methods and Static Methods in Python
The difference between instance methods, @classmethod (receives cls), and @staticmethod (receives neither self nor cls), with practical use cases.
Operator Overloading in Python
How to make Python's built-in operators (+, -, *, ==, <, etc.) work on your own classes by implementing the corresponding dunder methods.
Classes and Objects in Python
How Python's class statement defines a blueprint for objects, and how instances are created and used.
Constructors in Python
How __init__ initializes new objects, why it isn't really the constructor, and how default values work.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics