Lesson 6 · OKSTEM College · Associate of Science in Computer Science
What Are Dunder Methods?
Dunder (double-underscore) methods let your objects hook into Python's built-in operators and functions. Instead of calling obj.add(other), you write obj + other — Python calls obj.__add__(other) automatically.
classCountdown:
def__init__(self, start):
self.start = start
def__iter__(self):
self.current = self.start
returnselfdef__next__(self):
ifself.current < 0:
raiseStopIteration
val = self.current
self.current -= 1return val
for n inCountdown(3):
print(n, end=" ") # 3 2 1 0
Practice Problems
1. Add __len__ to Vector that returns the number of components (2).
def __len__(self):
return 2 # a 2D vector always has 2 components
2. When should you implement __repr__ vs __str__?
__repr__: unambiguous, developer-facing (shown in REPL, repr()).
Should ideally be eval-able: repr(obj) gives you code to recreate it.
__str__: readable, user-facing (shown by print(), str()).
If only one is defined, Python falls back to __repr__ for both.
Knowledge Check
Dunder methods are called
You can, but that's not the point — Python calls them implicitly.
Correct — writing obj + x triggers __add__ automatically.
They're called from anywhere, including outside the class.
Dunder methods work on any class.
Recap: obj + other → Python calls obj.__add__(other). You write the dunder; Python wires it to the operator.
print(obj) calls which dunder?
print() prefers __str__; it falls back to __repr__ if __str__ is missing.
Correct — print() and str() call __str__ first.
No such dunder exists.
No such dunder exists.
Recap: str(obj) / print(obj) → __str__. repr(obj) → __repr__. Define both when possible.
To make for x in obj work, your class needs
These dunders don't exist.
Correct — __iter__ sets up state and returns self; __next__ yields values and raises StopIteration when done.
No such dunder.
__getitem__ enables indexing; for full iterator protocol you need __iter__ + __next__.
Recap: the iterator protocol requires both __iter__ (returns the iterator object) and __next__ (returns the next value or raises StopIteration).
What does __eq__ control?
Assignment is not an operator in the same sense; __eq__ is for ==.
Correct — without __eq__, == compares object identity (same as is).
is always checks identity; you can't override it.
Hashing is controlled by __hash__, though __eq__ affects it too.
Recap: define __eq__ for value equality. If you define __eq__, Python sets __hash__ to None unless you also define it.
Implementing __add__ to return a new Vector (not modifying self) is good practice because
Vector doesn't inherit from ABC; this is a design choice.
Correct — operators should return new objects, like Python's built-in numbers do.
Python won't raise an error, but it's a bad pattern.
Immutability isn't inherently faster; it's about correctness.
Recap: arithmetic operators should return new instances. v1 + v2 returns a new Vector; v1 is unchanged. Mirrors how 1 + 2 works with ints.