Dunder Magic Methods (__repr__, __str__, __eq__, __hash__)
1Concept
Dunder (double underscore) methods implement standard Python object behaviors: `__repr__` provides an unambiguous developer representation; `__str__` provides user-friendly text; `__eq__` determines equality; `__hash__` enables storing instances in sets and dictionary keys.
2Architecture Diagram
obj == other ---> Calls obj.__eq__(other) hash(obj) ---> Calls obj.__hash__() (Must remain constant for set/dict keys!)
3Code Example
Python 3.12
class ServerNode:
def __init__(self, node_id: str, ip: str):
self.node_id = node_id
self.ip = ip
def __repr__(self):
return f"ServerNode(node_id={self.node_id!r}, ip={self.ip!r})"
def __eq__(self, other):
if not isinstance(other, ServerNode):
return False
return self.node_id == other.node_id
def __hash__(self):
return hash(self.node_id)
node1 = ServerNode("node-01", "192.168.1.10")
node2 = ServerNode("node-01", "10.0.0.5") # Same node_id
cluster = {node1, node2}
print(f"Cluster set: {cluster}")
print(f"Node representation: {repr(node1)}")4Expected Output
Cluster set: {ServerNode(node_id='node-01', ip='192.168.1.10')}
Node representation: ServerNode(node_id='node-01', ip='192.168.1.10')5Key Takeaways
- ✓If a class overrides `__eq__` without defining `__hash__`, Python sets `__hash__ = None` (unhashable).
- ✓Always ensure `__hash__` uses immutable fields that do not change over the object's lifetime.
- ✓`__repr__` should ideally look like valid Python code to recreate the object.