Lecții din modul (3/4)
Metode speciale (dunder)
Metode speciale (numite metode dunder pentru că încep și se termină
cu liniuță dublă: __name__) sunt cârligele care lasă obiectele tale
se integrează cu limba: reprezentare text, comparație cu ==,
suport pentru len(), in, operatori etc.
Ați folosit deja unul: __init__.
__str__ și __repr__
Ei controlează ceea ce apare cu print() și în 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 contenitoriDacă definiți doar __repr__, Python îl folosește și ca alternativă pentru
__str__.
__eq__: redefinirea ==
În mod implicit, a == b compară identificatorii obiectelor (is), nu
continutul lor. Pentru comparație structurală, definiți __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) # FalseSe returnează NotImplemented (un cuvânt cheie special, nu False!) când tipurile
nu sunt comparabile este practica corectă: Python va încerca apoi cu
alt operand __eq__.
__len__: suport pentru 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)Prin definirea __len__, obțineți și boolean gratuit: un obiect
cu len() == 0 devine fals.
Alte lucruri utile (prezentare generală)
__add__(self, other)→ redefinește+__lt__,__le__,__gt__,__ge__→ operatori de comparație__contains__(self, item)→ acceptăitem in self__iter__+__next__→ face obiectul iterabil__getitem__(self, key)→ acceptăself[key]__hash__→ trebuie să fie o cheie dict / element de set
Rândul tău
Definiți `Bani` cu __init__(self, amount, currency) și __str__ care returnează `f'{amount} {currency}'`. Creați `s = Money(42, 'EUR')` și evaluați `str(s)`.
Afișează indiciu
șir f în __str__.
Soluție disponibilă după 3 încercări
Exercițiu de revizuire
Definiți `Pereche` cu __init__(self, a, b) și __eq__ pe baza comparației structurale a (a, b). Evaluați `Pair(1, 2) == Pair(1, 2)`.
Afișează indiciu
Comparați tuplurile (self.a, self.b) == (other.a, other.b).
Soluție disponibilă după 3 încercări
Provocare suplimentară
Definiți o clasă \`Carte\` cu un constructor care ia \`titlu\` și \`autor\`. Definiți metoda specială \`__str__(self)\` astfel încât să returneze șirul \`"Titlu după autor"\` (de exemplu, \`'1984 de George Orwell'\`). Instanciați o carte și evaluați \`str(book)\`.
Afișează indiciu
Folosiți f"{self.title} de {self.author}" în def __str__(self):.
Soluție disponibilă după 3 încercări