Pular para o conteúdo principal

Apresentando os magic methods do Python

Descubra o que são os magic methods e entenda a diferença entre métodos e funções.
Atualizado 17 de set. de 2026  · 11 min lido

Explorar com IA

ChatGPTClaudePerplexity

Um dos fatores que tornam o Python uma linguagem de programação tão poderosa são os magic methods. Em alguns círculos de Pythonistas, você pode ouvi-los sendo chamados de ‘dunder methods’, por causa do padrão de dois underlines. 

O papel deles no Python é realizar um procedimento conhecido como ‘sobrecarga de operadores’ (operator overloading), que basicamente dá um significado estendido a um operador predefinido. Em outras palavras, usamos a sobrecarga de operadores para adicionar comportamentos personalizados às nossas classes e habilitar seu uso com os operadores e funcionalidades nativas do Python.  

Neste artigo, vamos nos aprofundar nos magic methods do Python, abordando: 

  • A diferença entre métodos e funções 
  • O que são magic methods
  • Alguns exemplos em Python. 

Confira este caderno no DataLab para acompanhar o código usado neste tutorial. 

Métodos vs. funções em Python

Antes de explicar o que são magic methods, precisamos entender as diferenças entre método e função em Python. 

O Python usa métodos para representar o comportamento de um objeto. Assim, métodos estão associados a um objeto e executam operações sobre os dados dentro desse objeto. Outro ponto distintivo é o parâmetro self, que deve sempre aparecer como o primeiro parâmetro passado ao método. 

Observação: não precisa ser literalmente a palavra self como primeiro parâmetro, mas a comunidade Pythonista concorda que é a melhor prática. 

# Exemplo de método
class Human:
    # Este é um método
    def walk(self):
        print("I am walking") 

Métodos dependem da classe à qual estão associados. Portanto, para chamar um método, é preciso criar uma instância da classe antes de acessá-lo com o operador de ponto. 

# Isso vai funcionar
joe = Human()
joe.walk()

"""
I am walking
"""




# Isso vai gerar um NameError
walk()

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/tmp/ipykernel_153/2327344440.py in <module>
      4
      5 # Isso vai gerar um NameError
----> 6 walk()

NameError: name 'walk' is not defined

Uma função, por outro lado, é diferente: não precisamos criar uma instância de classe. 

Funções em Python são passos executados como um bloco de código apenas quando chamadas. Elas são definidas de forma independente de qualquer objeto de classe, o que significa que podem ser chamadas diretamente pelo nome. Como não estão associadas a nenhuma classe, não precisamos passar self como parâmetro – parâmetros são opcionais. 

Em essência, uma função é simplesmente um conjunto de instruções bem definidas que o interpretador usa para executar uma tarefa. 

# Exemplo de função
def run():
  print("I am running.")
​
run()

"""
I am running.
"""

Como exploramos no artigo Como chamar e escrever funções, funções também vêm em dois tipos: nativas e definidas pelo usuário. 

  • Funções nativas (built-ins): funções incluídas na biblioteca padrão do Python. 
  • Funções definidas pelo usuário: funções definidas pelo usuário - o Python permite definir e usar suas próprias funções, que podem ser acessadas em um programa.  

Em muitos aspectos, métodos e funções são idênticos – ambos são definidos com a instrução def. A diferença é que métodos estão associados a um objeto e operam sobre os dados contidos em uma classe, enquanto funções são definidas de forma independente e podem ser chamadas pelo nome em qualquer lugar do programa. 

O que são os magic methods do Python?

No início do tutorial, mencionamos que magic methods também são chamados de dunder methods por conta do padrão de dois underlines. Isso quer dizer que todos os magic methods em Python começam e terminam com dois underlines. 

O magic method mais conhecido é o __init__, que permite inicializar uma classe com atributos específicos. 

class Employee:
    def __init__(self, name, age, role):
        self.name = name
        self.age = age
        self.role = role

Para instanciar essa classe, precisamos especificar os atributos name, age e role da instância. Por exemplo:

user_1 = Employee(name="John", age=24, role="Data Scientist")

Se não fizermos isso, será levantado um TypeError

O método __init__ faz parte da categoria de magic methods de inicialização e construção, mas é só um entre vários. A tabela abaixo mostra outros métodos dessa categoria. 

__new__(cls, other)

Usado para criar uma nova instância de uma classe

__init__(self, other)

Chamado depois que uma nova instância é criada; todos os atributos passados ao construtor da classe serão usados como atributos. 

__del__(self)

Também conhecido como destrutor; chamado quando uma instância vai ser destruída. 

A forma mais simples de entender os magic methods é como um contrato entre a sua implementação e o interpretador do Python. Uma das cláusulas exige que o Python realize certas ações nos bastidores a partir de determinadas situações, como inicializar uma instância de classe com objetos específicos. 

Em outras palavras, não é sua responsabilidade invocar um magic method diretamente – o Python faz isso por você, por baixo do capô. 

Métodos de representação em string

Python é uma linguagem de programação orientada a objetos (POO) – tudo em Python é um objeto. Quando um novo objeto é criado, implicitamente criamos um objeto relacionado porque todas as classes herdam de object.  

Observação: você também pode tornar a herança explícita passando a classe object para a sua classe. 

# Funciona
class Car:
  pass
​
# Também funciona
class Vehicle(object):
  pass
​
car = Car()
vehicle = Vehicle()
​
print(car, vehicle, sep="\n")

"""
<__main__.Car object at 0x7f80449dc0a0>
<__main__.Vehicle object at 0x7f80449dc1f0>
"""

No código acima, criamos duas classes vazias, mas o interpretador ainda soube o que imprimir quando chamamos print. Isso é possível porque todas as classes herdam da classe object (a mãe de todas as classes no Python), que possui um magic method chamado __repr__, o qual o print chama para retornar um valor ao nosso programa principal.  

Quem já conhece herança sabe que uma classe filha pode sobrescrever sua classe pai definindo seu próprio método com o mesmo nome. 

# Sobrescrevendo o __repr__ de object
class Vehicle:
  def __repr__(self):
      return f"{self.__class__.__qualname__}"
​
vehicle = Vehicle()
print(vehicle)

"""
Vehicle
"""

Você também pode usar o magic method __str__ para criar uma representação em string que é chamada pelo print. 

Na verdade, o __repr__ funciona como comportamento de fallback do __str__. Assim, quando chamamos print, o Python primeiro procura o método __str__ definido na sua classe e, se não encontrar, recorre ao __repr__. 

# Usando __str__ para representação em string
class Vehicle:
  def __str__(self):
      return f"{self.__class__.__qualname__}"
     
vehicle = Vehicle()
print(vehicle)

"""
Vehicle
"""

A tabela abaixo lista outros magic methods de representação em string. 

__str__(self)

Chamado pela função nativa str() do Python e pelo print para exibir a representação informal em string de um objeto. Observe que não precisa ser uma expressão Python válida. 

__repr__(self)

Chamado pela função nativa repr() do Python e por conversões de string para exibir a representação oficial em string de um objeto. Idealmente, deve parecer uma expressão Python válida, mas, se não for possível, uma string com uma descrição útil é preferida. 

__unicode__(self)

Chamado para implementar a função nativa unicode() do Python e retorna um objeto Unicode. 

__hash__(self)

Chamado pela função nativa hash() do Python e por operações em membros de coleções com hash. O método deve retornar um inteiro. 

__nonzero__(self)

Chamado pela operação nativa bool() do Python para implementar testes de verdade. O método deve retornar True ou False (ou seus equivalentes inteiros 1 ou 0). 

Métodos "mágicos" de encapsulamento 

Encapsulamento é um dos conceitos fundamentais da programação orientada a objetos (POO). Ele se refere a agrupar dados com os métodos que operam sobre esses dados ou restringir o acesso direto a certos componentes dentro de um objeto.

Desenvolvedores vindos de outras linguagens de POO costumam criticar o fato de o Python não adotar encapsulamento de forma tão explícita nas classes. Eles estão acostumados a modificadores para métodos ou campos que permitem definir, por exemplo, atributos privados com getters e setters públicos. No Python, boa parte do encapsulamento acontece via magic methods. 

Por exemplo, __setattr__ é uma solução de encapsulamento que nos permite definir o comportamento da atribuição a um atributo, exista ele previamente ou não. Em outras palavras, é possível definir regras para mudanças nos valores dos atributos. 

import string

class Alphabet():
    def __setattr__(self, name, value):
        self.__dict__[name] = value.upper()

a = Alphabet()

# Atribuindo um atributo que não existe
# O setattr deve convertê-lo para maiúsculas mesmo tendo sido definido em minúsculas
a.alphabet = string.ascii_lowercase
print(a.alphabet)

No código acima, criamos uma classe chamada Alphabet sem atributos, mas informamos ao Python que queríamos colocar em maiúsculas qualquer atributo definido na instância da classe.

Sabemos que POO pode parecer distante para alguns leitores. Para ficar em dia com POO em Python, confira a Python Programmer Track da DataCamp.   

Métodos mágicos matemáticos

Outra categoria de magic methods do Python são os métodos matemáticos (também conhecidos como operadores aritméticos). Expressões são criadas usando símbolos especiais chamados ‘operadores’ no Python. Usar esses operadores em uma expressão envolve criar objetos com magic methods matemáticos. Se isso não for atendido, será levantado um TypeError. 

class Numbers:
  def __init__(self, a, b):
      self.a = a
      self.b = b
   
set_a = Numbers(2, 4)
set_b = Numbers(3, 5)
​
print(set_a + set_b)
"""
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_152/3639634723.py in <module>
      7 set_b = Numbers(3, 5)
      8
----> 9 print(set_a + set_b)

TypeError: unsupported operand type(s) for +: 'Numbers' and 'Numbers'
"""

No código acima, tentamos criar múltiplas instâncias da classe Numbers e somá-las, o que gerou um erro como esperado. Uma solução seria criar um método na nossa classe para somar números, mas isso impediria a criação de expressões. 

Uma solução melhor é implementar o magic method __add__ assim:  

# Usando o operador de soma
class Numbers:
    def __init__(self, a, b):
        self.a = a
        self.b = b
   
    def __add__(self, other):
        # Permitir apenas a soma de objetos Numbers
        if not isinstance(other, Numbers):
            return NotImplemented
        return Numbers(other.a + self.a, other.b + self.b)
   
    def __repr__(self):
      return f"{self.__class__.__qualname__}({self.a}, {self.b})"
   
a = Numbers(2, 4)
b = Numbers(3, 5)
print(a + b) # Deve resultar em Numbers(5, 9)


"""
RandomNumbers(5, 9)
"""

O exemplo acima só permite somar dois objetos Numbers. Vamos implementar outro método matemático que permita multiplicar um objeto Numbers por um inteiro. 

# Multiplicando Numbers por um inteiro
class Numbers:
    def __init__(self, a, b):
        self.a = a
        self.b = b
   
    def __add__(self, other):
        # Permitir apenas a soma de objetos Numbers
        if not isinstance(other, Numbers):
            return NotImplemented
        return Numbers(other.a + self.a, other.b + self.b)
   
    def __mul__(self, other):
      if not isinstance(other, int):
          return NotImplemented
         
      return Numbers(self.a * other, self.b * other)
   
    def __repr__(self):
      return f"{self.__class__.__qualname__}({self.a}, {self.b})"
   
a = Numbers(2, 4)
print(a * 5) # Deve retornar 10, 20




"""
RandomNumbers(10, 20)
"""

No código acima, adicionamos o magic method __mul__ para permitir multiplicar os números da nossa classe personalizada por um inteiro. 

Perceba que o objeto Numbers aparece no lado esquerdo do operador *. Isso não é por acaso. Vamos colocá-lo no lado direito do operando e ver o que acontece. 

- snip --

a = Numbers(2, 4)
print(3 * a)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_152/2857655049.py in <module>
      1 a = Numbers(2, 4)
----> 2 print(3 * a)

TypeError: unsupported operand type(s) for *: 'int' and 'Numbers'

O Python lança um TypeError. 

O __mul__ que implementamos só trata o caso em que o objeto Numbers está à esquerda do operador *. Para estender essa funcionalidade, precisamos adicionar o método reverso, __rmul__. 

# Habilitando multiplicação reversa
class Numbers:
    def __init__(self, a, b):
        self.a = a
        self.b = b
   
    def __add__(self, other):
        # Permitir apenas a soma de objetos Numbers
        if not isinstance(other, Numbers):
            return NotImplemented
        return Numbers(other.a + self.a, other.b + self.b)
   
    def __mul__(self, other):
      if not isinstance(other, int):
          return NotImplemented
      return Numbers(self.a * other, self.b * other)

    def __rmul__(self, other):
        return self.__mul__(other)
   
    def __repr__(self):
      return f"{self.__class__.__qualname__}({self.a}, {self.b})"
   
a = Numbers(2, 4)
print(5 * a) # Deve retornar 10, 20

"""
Numbers(10, 20)
"""

Agora podemos criar uma expressão de multiplicação sem nos preocupar com o lado do operando em que o objeto Numbers aparece. 

Conclusão

O princípio básico para aproveitar os magic methods do Python é o mesmo: criar uma classe e sobrescrever os magic methods de object. Existem muitos magic methods em Python, o que tornaria este um tutorial enorme se fôssemos cobrir todos individualmente. Recomendamos fortemente consultar a documentação do Python para ter uma visão completa dos magic methods que você pode usar para aprimorar suas habilidades de programação em Python.  



Tópicos
Python

Cursos de Python

Curso

Python intermediário

4 h
1.4M
Aumente o nível de suas habilidades em ciência de dados criando visualizações usando Matplotlib e manipulando DataFrames com pandas.
Ver detalhesRight Arrow
Iniciar Curso
Ver maisRight Arrow
Relacionado
Data Skills

blog

6 práticas recomendadas de Python para um código melhor

Descubra as práticas recomendadas de codificação Python para escrever os melhores scripts Python da categoria.
Javier Canales Luna's photo

Javier Canales Luna

13 min

Tutorial

Funções em Python: como chamar e escrever funções

Descubra como escrever funções em Python reutilizáveis e eficientes. Domine parâmetros, instruções de retorno e temas avançados como funções lambda. Organize melhor seu código com main() e outras boas práticas.
Karlijn Willems's photo

Karlijn Willems

14 min

Tutorial

Tutorial e exemplos de funções e métodos de listas Python

Aprenda sobre as funções e métodos da lista Python. Siga agora os exemplos de código para list() e outras funções e métodos Python!
Abid Ali Awan's photo

Abid Ali Awan

7 min

Tutorial

Tutorial sobre concatenação de strings em Python

Aprenda vários métodos para concatenar strings em Python, com exemplos para ilustrar cada técnica.
DataCamp Team's photo

DataCamp Team

5 min

Tutorial

30 truques de Python para escrever um código melhor (com exemplos)

Selecionamos 30 truques de Python para você melhorar seu código e desenvolver suas habilidades em Python.
Kurtis Pykes 's photo

Kurtis Pykes

15 min

Tutorial

Como cortar uma string em Python: Três métodos diferentes

Aprenda o básico sobre como cortar caracteres à esquerda e à direita de uma string em Python.
Adel Nehme's photo

Adel Nehme

6 min

Ver MaisVer Mais