Métodos mágicos em Python

Olá Pessoal 🖖 Este artigo tem intuíto de explicar o que são os métodos mágicos do python para quem está aprendendo a linguagem.

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.

Conclusão

Vimos alguns dos métodos mágicos mais conhecidos da linguagem, no entanto, há uma variedade que também são muito úteis, então, listarei referências a seguir. Por fim, fico feliz que tenha chegado ao fim do post, sinta-se livre para sugerir melhorias, ou dar seu feedback sobre o que achou dele. Obrigado 🙏

show demais =D

[PYTHON] Esses métodos não conhecia, salvando a tab para anotações mais tarde.

Fenomenal! Mostra algo incrível de uma forma simples e didática.

Eu adoro o conceito da criação de classes, esses métodos "padrões" das classes possibilitam inúmeras implementações, esses dias eu estava vendo sobre Dataclasses com o Otávio Mesquita e fiquei surpreso com o que é possível de se fazer com as classes.

Que bom, **joaocastro**! Vou dar uma olhada no video que recomendou, existe várias estruturas que o python fornece para termos mais expressividade para definir objetos. Além de Dataclasses eu também acho bem legal os tipos [`Enum`](https://docs.python.org/3/library/enum.html) e [`namedtuple`](https://docs.python.org/3/library/collections.html#collections.namedtuple).

Que interessante! eu estou iniciando no estudo de python (atualmente utilizo apenas para resolver exercícios de algoritmos) e sempre me perguntei o que diabos eram esses metódos com dois underlines no inicio e ao fim. Esse teu post me deu o ânimo e a curiosidade para buscar além.

Valeu parça!

Que bom que gostou **BrauUu**! Para esclarecer, quando usa-se dois underlines no início e fim, trata-se de métodos mágicos. No entanto, quando usa-se atributos com dois underlines no início, sem underlines no fim, trata-se de atributos/métodos privados, por exemplo `__atributo_tal`, nesse caso, é uma convenção.
No caso de uso em classes em específico não é uma convenção exatamente. Por exemplo, supondo que tenha uma classe qualquer: ``` class Example: def __init__(self, atributo_tal) -> None: self.__atributo_tal = atributo_tal ``` E após isso você a instancie e tente acessar o atributo `__atributo_tal` da instância, como demonstrado a seguir: ``` example = Example("um valor qualquer") print(example.__atributo_tal) ``` Fazendo isso você se depararia com um `AttributeError`, por causa do conceito de `name mangling` do python. ``` AttributeError: 'Example' object has no attribute '__atributo_tal' ``` Mas de fato existe uma convenção, e ela se dá de maneira parecida com o que mencionou acima. Ao invés de `__atributo_tal` seria `_atributo_tal`, com apenas um único _.

Achei interessante a repercussão que a publicação teve! As vezes pensamos que o conhecimento é básico, trivial, mas pode não ser para muitos! E é importante compartilhar isso. Muito bem!

Bem pontuado, **DeividBraian**, eu também tive essa impressão. Pois, pensando em temas para escrever no tabnews, as primeiras opções eram temas mais avançados da linguagem, mas percebi que seria mais útil temas para quem está iniciando na linguagem.
shoow! continue compartilhando! aproveite para bombar o linkedin também.

nunca imaginei que python teria esses recursos, se pa vou acabar precisando um dia. Isso me lembrou muito os spread operator do c++, só que de maneira mais simples

Eu não conheço esse termo em c++, tem alguma referência para me recomendar sobre o tema? De qualquer forma, o conceito que mostrei pode ser visto em várias linguagens, é um conceito chamado de sobrecarga de operadores. Veja um [exemplo em c++](https://www.geeksforgeeks.org/operator-overloading-c/).

Já me perguntaram isso em entrevista de emprego.