Métodos mágicos são métodos de uma classe cujo nome do método possui a seguinte característica: são prefixados com underline e sufixados com underline, por exemplo: __add__. Devido a isso, também são chamados de Dunder methods, onde dunder significa Double Underscores.
Estes métodos têm significado especial para a linguagem e são utilizados para implementar alguns comportamentos, por exemplo, implementar +(soma) em um objeto definido pelo usuário. Mostrarei alguns exemplos comuns a seguir.
Criando objetos com métodos mágicos
O método mágico mais conhecido em python, provavelmente, é __init__. Ele é utilizado para inicializar os atributos de um objeto. Outro método também conhecido é o __str__, utilizado para representar via texto um objeto. Como exemplo, o seguinte trecho define uma classe para representar a moeda real:
class Real:
def __init__(self, value=0):
self.value = value
def __str__(self):
return 'R$ {:0.2f}'.format(self.value)
print(Real(10)) # Imprime: R$ 10.00
Implementado operadores aritméticos em objetos
No exemplo anterior criamos objetos para representar um valor monetário, real. E se quisermos somar nossos reais? No código anterior, não conseguimos pois o valor monetário é um objeto, e não um número. Como solução, podemos utilizar métodos mágicos para conseguir somar, algo como Real(10) + Real(20).
Em python, os operadores aritméticos podem ser implementados em qualquer objeto. Para fazer isso, basta que a classe destes objetos implemente os métodos __add__(para soma), __sub__(para subtração), __mul__(para multiplicação) e outros métodos para outras operações aritméticas.
Portanto, iremos implementar a soma nos nossos objetos do tipo Real:
class Real:
def __init__(self, value=0):
self.value = value
def __str__(self):
return 'R$ {:0.2f}'.format(self.value)
def __add__(self, money):
return Real(self.value + money.value)
real10 = Real(10)
real20 = Real(20)
print(real10 + real20) # Imprime: R$ 30.00
Ao usarmos + o python percebe que o objeto implementa __add__, então, chama este método como resultado da soma.
E se quisermos comparar os nossos objetos reais? Por exemplo, saber qual objeto é maior. Para isso, podemos implementar os métodos __gt__ que é chamado ao utilizar >, e __lt__ que é chamado ao usar o operador <. Veja o exemplo:
class Real:
def __init__(self, value=0):
self.value = value
def __gt__(self, money):
return self.value > money.value
def __lt__(self, money):
return self.value < money.value
print(Real(10) > Real(20)) # Imprime: False
print(Real(10) < Real(20)) # Imprime: True
Podemos implementar também as relações ==, !=. Podemos melhorar nosso Real implementando conversão para dólar, adição entre real e dólar, ou até mesmo outros operadores aritméticos. Fica como lição de casa para o leitor.
