Module lessons (3/4)
Special methods (dunder)
Special methods (called dunder methods because they begin and end
with a double underscore: __name__) are the hooks that let your objects
integrate with the language: text representation, comparison with ==,
support for len(), in, operators, etc.
You have already used one: __init__.
__str__ and __repr__
They control what appears with print() and in the REPL.
class Punto:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Punto({self.x}, {self.y})"
def __str__(self):
return f"({self.x}, {self.y})"
p = Punto(3, 4)
str(p) # '(3, 4)' — per umani
repr(p) # 'Punto(3, 4)' — per debugger / dev
print(p) # '(3, 4)'
p # Punto(3, 4) in REPL → repr
[p, p] # [Punto(3, 4), Punto(3, 4)] — sempre repr nei contenitoriIf you define only __repr__, Python also uses it as a fallback for
__str__.
__eq__: redefining ==
By default a == b compares the identifiers of the objects (is), not
their contents. For structural comparison, define __eq__:
class Punto:
def __init__(self, x, y):
self.x, self.y = x, y
def __eq__(self, other):
if not isinstance(other, Punto):
return NotImplemented
return (self.x, self.y) == (other.x, other.y)
Punto(1, 2) == Punto(1, 2) # True
Punto(1, 2) == Punto(3, 4) # FalseReturning NotImplemented (a special keyword, not False!) when the types
are not comparable is the correct practice: Python will then try with the
other operand's __eq__.
__len__: support for len()
class Cesto:
def __init__(self):
self.frutti = []
def __len__(self):
return len(self.frutti)
c = Cesto()
c.frutti.append("mela")
len(c) # 1
bool(c) # True (len > 0)By defining __len__, you also get the boolean for free: an object
with len() == 0 becomes falsy.
Other useful dunders (overview)
__add__(self, other)→ redefines+__lt__,__le__,__gt__,__ge__→ comparison operators__contains__(self, item)→ supportsitem in self__iter__+__next__→ makes the object iterable__getitem__(self, key)→ supportsself[key]__hash__→ required to be a dict key / set element
Your turn
Define `Money` with __init__(self, amount, currency) and __str__ that returns `f'{amount} {currency}'`. Create `s = Money(42, 'EUR')` and evaluate `str(s)`.
Show hint
f-string in __str__.
Solution available after 3 attempts
Review exercise
Define `Pair` with __init__(self, a, b) and __eq__ based on the structural comparison of (a, b). Evaluate `Pair(1, 2) == Pair(1, 2)`.
Show hint
Compare the tuples (self.a, self.b) == (other.a, other.b).
Solution available after 3 attempts
Additional challenge
Define a class `Book` with a constructor taking `title` and `author`. Define the special method `__str__(self)` so it returns the string `"Title by Author"` (e.g. `'1984 by George Orwell'`). Instantiate a book and evaluate `str(book)`.
Show hint
Use f"{self.title} by {self.author}" inside def __str__(self):.
Solution available after 3 attempts