Python · The language, not just syntax
Which dunder methods matter most and what contracts do they carry?
Short answer
Dunder methods hook objects into Python protocols: __repr__ and __str__ for display, __eq__ and __hash__ for comparison, __len__ and __getitem__ for containers, and __call__ for callables.
Dunder methods are looked up on the type, not the instance, which is why special method behaviour is consistent for built-ins. Implementing them lets your objects work with len, ==, iteration, indexing, arithmetic, context managers and the with statement.
class Money:
def __init__(self, cents, currency="USD"):
self.cents = cents
self.currency = currency
def __repr__(self):
return "Money(" + str(self.cents) + ", " + self.currency + ")"
def __eq__(self, other):
if not isinstance(other, Money):
return NotImplemented
return (self.cents, self.currency) == (other.cents, other.currency)
def __hash__(self):
return hash((self.cents, self.currency))
def __add__(self, other):
if self.currency != other.currency:
raise ValueError("currency mismatch")
return Money(self.cents + other.cents, self.currency)
print(Money(500) + Money(250))Contracts to respect
- __repr__ should be unambiguous and ideally evaluable; __str__ is for users
- If you define __eq__, define __hash__ too or the object becomes unhashable
- Equal objects must have equal hashes, or dict and set behaviour breaks
- __getitem__ should raise IndexError for out-of-range access so iteration works
Do not overload operators with surprising meanings. A __add__ that mutates one operand or performs I/O will confuse anyone reading the call site. When in doubt, a named method communicates intent better than an operator.
Follow-ups you should expect
Interviewers use these to check whether the first answer was understanding or memorisation.
- 1What is the difference between __repr__ and __str__?
- 2What happens if you define __eq__ without __hash__?
- 3Why return NotImplemented instead of raising TypeError?
- 4How does __getitem__ make an object iterable?
Say it in the interview
Dunder methods integrate objects with Python protocols. I implement __repr__ for developers, __str__ for users, and __eq__ with a matching __hash__ so equal values behave correctly in dicts and sets. For operators I return NotImplemented on unsupported types so Python can try the reflected operation. I avoid operator overloading when a named method would communicate the behaviour more clearly.
Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.
Related questions
Reading is step one
Now say it out loud.
Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Python mock interview and get scored feedback on depth, clarity and confidence.