Python POO Intermediário
Métodos especiais
Em Python, os métodos especiais (ou dunder methods, de double underscore) permitem que objetos de classes personalizadas se comportem como tipos nativos. Eles são chamados automaticamente pelo interpretador em situações específicas, como ao imprimir um objeto (__str__, __repr__), comparar (__eq__), calcular hash (__hash__), obter comprimento (__len__), iterar (__iter__) ou usar operadores (__add__, __sub__, etc.).
Implementar esses métodos torna suas classes mais expressivas e integradas à linguagem. Por exemplo, ao definir __eq__, você pode comparar objetos com ==; com __hash__, eles podem ser usados como chaves de dicionário ou em conjuntos; com __len__, a função len() funciona; e com __iter__, você pode percorrer o objeto em um for.
Neste card, vamos explorar os métodos especiais mais comuns e mostrar como eles permitem que suas classes se comportem como coleções, números ou qualquer outra abstração que você imaginar. O segredo é lembrar que eles nunca são chamados diretamente (exceto em casos raros), mas sim pelo interpretador quando você usa a sintaxe correspondente.
Pontos-chave
__repr__fornece uma representação oficial e não ambígua do objeto, usada em debugging;__str__é a versão amigável para usuários.__eq__define igualdade personalizada; se implementado,__hash__deve ser consistente para permitir uso em sets e dicionários.__len__e__iter__permitem que objetos se comportem como coleções, suportandolen()e iteração.- Operadores como
+,-,*podem ser implementados com__add__,__sub__,__mul__, etc., possibilitando aritmética personalizada. - Métodos especiais são chamados implicitamente pelo interpretador; não os invoque diretamente a menos que saiba o que está fazendo.
class Vetor:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'Vetor({self.x}, {self.y})'
def __str__(self):
return f'({self.x}, {self.y})'
def __eq__(self, other):
if not isinstance(other, Vetor):
return NotImplemented
return self.x == other.x and self.y == other.y
def __hash__(self):
return hash((self.x, self.y))
def __add__(self, other):
if not isinstance(other, Vetor):
return NotImplemented
return Vetor(self.x + other.x, self.y + other.y)
def __len__(self):
return 2 # um vetor tem duas coordenadas
def __iter__(self):
yield self.x
yield self.y
v1 = Vetor(1, 2)
v2 = Vetor(3, 4)
print(repr(v1)) # Vetor(1, 2)
print(str(v1)) # (1, 2)
print(v1 == Vetor(1, 2)) # True
print(len(v1)) # 2
print(list(v1)) # [1, 2]
print(v1 + v2) # Vetor(4, 6)
print(hash(v1) == hash(Vetor(1, 2))) # True