Pular para o conteúdo principal

Métodos Python Dunder: Comandos especiais que vale a pena conhecer

Saiba como os métodos de sublinhado duplo do Python permitem que seus objetos personalizados trabalhem naturalmente com operações integradas, desde a impressão até a aritmética. Descubra como esses métodos mágicos simplificam o design da classe e liberam comportamentos poderosos.
Actualizado 11 de abr. de 2025  · 8 min de leitura

Você já se perguntou como o Python faz com que suas classes personalizadas funcionem perfeitamente com as funções integradas? Isso se deve aos métodos "dunder" - abreviação de métodos de sublinhado duplo.

Imagine que você esteja criando uma classe para números complexos e queira usar o operador + naturalmente. Em vez de escrever código extra para lidar com a adição, você define um método __add__ e o Python cuida do resto.

Esses métodos mágicos, como __init__ para a criação de objetos e __str__ para a representação de strings, são invocados automaticamente pelo Python, de modo que você não precisa chamá-los diretamente. Eles evitam conflitos de nomenclatura com seus métodos regulares e potencializam recursos como sobrecarga de operador e comportamento personalizado.

Seja instanciando objetos, realizando operações aritméticas ou simplesmente imprimindo um objeto, os métodos do dunder trabalham silenciosamente em segundo plano para tornar seu código mais elegante e eficiente. Se você é novo no Python e quer se atualizar sobre algumas das principais ideias, faça nosso curso de Introdução ao Python para ter uma boa base.

O que são métodos Dunder em Python?

Como comecei a mencionar, os métodos dunder do Python são métodos únicos, ou "mágicos", que formam a espinha dorsal do modelo de dados do Python, permitindo que suas classes personalizadas se integrem às operações internas do Python. Esses operadores incluem coisas como impressão, comparação e execução de aritmética.

Quando você define métodos como __init__ para inicializar objetos, __repr__ e __str__ para representação de objetos ou mesmo __del__ para limpeza, você está basicamente dizendo ao Python como lidar com operações padrão para seus objetos. O interpretador chama automaticamente esses métodos quando a operação correspondente é executada. Essa automação integrada cria uma ponte entre os recursos nativos do Python e as classes definidas pelo usuário.

Mais tarde, veremos exemplos de classes que usam esses métodos e outras que não usam, para que você possa ver como tudo isso funciona.

Categorias de métodos Dunder

Vamos explorar as principais categorias de métodos de dunder e ver como eles fortalecem seu código.

1. Inicialização e construção

Os métodos Dunder, como __new__, __init__ e __del__, controlam como os objetos são criados, inicializados e, por fim, destruídos.

  • __new__ vs. __init__: __new__ é responsável por criar uma nova instância, enquanto __init__ a inicializa. Essa separação é importante quando se trabalha com tipos imutáveis, nos quais você pode substituir o __new__ por outra coisa.

  • __del__: Esse método funciona como um destruidor, permitindo a limpeza quando um objeto está prestes a ser coletado como lixo.

Você pode até mesmo personalizar __new__ em classes imutáveis para impor regras de criação específicas.

2. Métodos numéricos e aritméticos

Os métodos Dunder, como __add__, __sub__, __mul__ e suas variantes in-place, permitem que seus objetos suportem operações aritméticas. Isso é conhecido como sobrecarga de operador. Ao definir esses métodos, você pode ativar o comportamento aritmético natural para seus objetos personalizados.

Por exemplo, sobrecarregue __add__ em uma classe Vector para adicionar os elementos correspondentes de dois vetores. Isso é particularmente útil ao projetar aulas que modelam conceitos matemáticos ou instrumentos financeiros.

3. Métodos de comparação e igualdade

Métodos como __eq__, __lt__ e __gt__ determinam como os objetos são comparados. Esses métodos permitem que você defina o que significa dois objetos serem iguais ou como eles devem ser ordenados.

Um exemplo típico é a comparação das áreas de duas formas: você pode substituir o endereço __lt__ para retornar true se a área de uma forma for menor que a da outra. Isso pode ser útil em coleções ou algoritmos de classificação.

4. Métodos de representação de strings

Os métodos __str__ e __repr__ controlam como os objetos são exibidos como cadeias de caracteres.

  • __repr__ deve fornecer uma representação amigável ao desenvolvedor que possa ser usada para recriar o objeto.

  • __str__ concentra-se em uma tela fácil de usar.

5. Métodos de contêineres e iteráveis

Para permitir que seus objetos se comportem como sequências ou contêineres, você pode implementar métodos como __len__, __getitem__ e __iter__. Isso permite operações como indexação, iteração e testes de associação.

Por exemplo, se você criar uma pilha ou lista personalizada, a implementação desses métodos permitirá que você use funções internas como len().

6. Capacidade de chamada e programação funcional

Com o método __call__, as instâncias de sua classe podem ser invocadas como funções. Isso é particularmente útil para criar objetos de função com estado que podem armazenar resultados em cache ou manter o estado interno entre as chamadas. Pense nisso como se estivesse transformando seu objeto em um minicomputador que você pode chamar repetidamente com parâmetros diferentes.

7. Gerentes de contexto

A implementação dos métodos __enter__ e __exit__ permite que seus objetos sejam usados com a declaração para gerenciamento de recursos. Isso é fundamental para o gerenciamento de recursos, como manipuladores de arquivos ou conexões de rede, garantindo que eles sejam configurados e limpos corretamente.

Um cenário do mundo real é usar um gerenciador de contexto personalizado para abrir e fechar conexões de banco de dados com segurança.

8. Acesso e descritores de atributos

Métodos como __getattr__, __setattr__ e __delattr__ permitem que você controle como os atributos são acessados e modificados. O protocolo do descritor refina ainda mais isso, permitindo que os objetos gerenciem o acesso aos atributos dinamicamente.

Por exemplo, um descritor pode validar ou transformar valores de atributos, garantindo que eles atendam a critérios específicos antes de serem definidos.

Métodos avançados e diversos da Dunder  

Embora os métodos principais do dunder cubram a maioria dos casos de uso, o Python inclui métodos avançados e especializados para tarefas como programação assíncrona, metaprogramação e comportamento específico da biblioteca. Por exemplo:  

  • Métodos assíncronos: Métodos como __aiter__ e __anext__ permitem a iteração assíncrona, enquanto __await__ oferece suporte a objetos aguardáveis.  

  • Ganchos de metaprogramação: Métodos como __prepare__ e __set_name__ permitem a criação dinâmica de classes e a nomeação de atributos.  

  • Métodos específicos da biblioteca: Bibliotecas como NumPy ou Pandas geralmente definem métodos dunder personalizados (por exemplo, __array__ para integração com NumPy).

Esses métodos avançados são normalmente usados para tarefas especializadas, de modo que a maioria dos desenvolvedores não precisará deles diariamente. No entanto, elas demonstram a flexibilidade e a profundidade do Python. Recomendo que você explore a documentação oficial do modelo de dados Python para obter uma lista completa. Esse recurso fornece detalhes abrangentes sobre todos os métodos de lavagem de roupas e seu uso pretendido.

Todos os métodos Dunder em Python

O Python fornece mais de 100 métodos dunder, cada um projetado para controlar diferentes aspectos do comportamento do objeto. Embora tenhamos explorado as principais categorias neste artigo, aqui está um resumo de alto nível para que você possa usá-lo como referência rápida:

  • Métodos aritméticos: Métodos como __add__, __sub__, __mul__ e __truediv__ permitem que seus objetos suportem operadores (+, -, *, /).

  • Métodos de comparação: Métodos como __eq__, __lt__ e __gt__ definem como os objetos são comparados em termos de igualdade ou ordem.

  • Gerenciamento de atributos: Com métodos como __getattr__, __setattr__ e __delattr__, você pode controlar o acesso aos atributos e implementar comportamentos dinâmicos.

  • Inicialização e construção: __new__, __init__ e __del__ gerenciam a criação, a inicialização e a limpeza de objetos, respectivamente.

  • Representação de cadeias de caracteres: Métodos como __str__ e __repr__ determinam como os objetos são representados como cadeias de caracteres, o que ajuda a gerar resultados fáceis de usar.

  • Iteração e comportamento do contêiner: Implemente __iter__ e __next__ para tornar seus objetos iteráveis e outros métodos para dar suporte à indexação e à recuperação de comprimento.

  • Capacidade de chamada: __call__ Permite que uma instância seja chamada como uma função, possibilitando um estilo de programação funcional com comportamento de estado.

  • Gerenciamento de contexto: Com __enter__ e __exit__, os objetos podem ser usados com declarações para gerenciar os recursos adequadamente.

  • Ganchos de metaprogramação: Métodos como __init_subclass__ oferecem maneiras de personalizar a criação e o comportamento da classe de forma dinâmica.

Consulte a documentação oficial do Python Data Model para obter uma lista completa e detalhada desses métodos dunder e suas funcionalidades. Esse recurso abrangente ajudará você a desbloquear todo o poder do modelo de objeto do Python e a criar códigos mais elegantes e eficientes.

Exemplos do mundo real e casos de uso

Vamos explorar como os métodos dunder podem potencializar os cenários do mundo real por meio de alguns exemplos.

Sobrecarga do operador

Imagine que você tenha uma classe numérica ou de cadeia de caracteres personalizada. Ao implementar métodos dunder como __add__ ou __mul__, você permite que seus objetos trabalhem naturalmente com operadores aritméticos. Você pode adicionar, subtrair ou multiplicar instâncias da mesma forma que faria com os tipos incorporados, fazendo com que suas classes personalizadas se misturem perfeitamente com as operações aritméticas do Python.

class Vector:
   def __init__(self, x, y):
        self.x = x
        self.y = y
   def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
   def __str__(self):
        return f"Vector({self.x}, {self.y})"

# Usage
v1 = Vector(1, 2)
v2 = Vector(3, 4)

result = v1 + v2
print(result)  # Output: Vector(4, 6)

Armazenamento em cache com capacidade de chamada

Você já quis evitar a repetição de cálculos caros? Ao implementar o método __call__, você pode fazer com que um objeto se comporte como uma função que armazena seus resultados em cache. Isso permite que você armazene o resultado de um cálculo pesado e o retorne rapidamente em chamadas subsequentes, otimizando o desempenho e economizando um valioso tempo de processamento.

class CachedComputation:
   def __init__(self):
        self.cache = {}
   def __call__(self, x):
        if x not in self.cache:
            self.cache[x] = self._expensive_computation(x)
        return self.cache[x]
   def _expensive_computation(self, x):
        # Imagine a complex calculation here
        return x ** 2

# Usage
compute = CachedComputation()

print(compute(5))  # Computes and caches: Output: 25
print(compute(5))  # Retrieves from cache: Output: 25

Gerenciadores de contexto personalizados

A criação de um gerenciador de contexto usando os métodos __enter__ e __exit__ permite que você automatize o gerenciamento de recursos. Por exemplo, você pode criar um gerenciador de contexto personalizado para lidar com operações de arquivo - abrir um arquivo quando você entra em um bloco e garantir que ele seja fechado quando você sair. Isso simplifica seu código e evita erros comuns, como vazamento de recursos.

class FileHandler:
   def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
   def __enter__(self):
        self.file = open(self.filename, self.mode)
        return self.file
   def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

# Usage
with FileHandler("example.txt", "r") as file:
    content = file.read()
    print(content)

Iteráveis e contêineres personalizados

Para que seus contêineres personalizados funcionem com os loops e as compreensões do Python, implemente o protocolo de iteração definindo métodos como __iter__ e __next__. Se você estiver criando uma pilha personalizada, uma fila ou qualquer outro contêiner, esses métodos permitem que seus objetos sejam repetidos como uma lista normal, aumentando a flexibilidade e a usabilidade das suas classes.

class Stack:
   def __init__(self):
        self.items = []
   def push(self, item):
	self.items.append(item)
   def pop(self):
        return self.items.pop()
   def __iter__(self):
        self.index = 0
        return self
   def __next__(self):
        if self.index >= len(self.items):
            raise StopIteration
        item = self.items[self.index]
        self.index += 1
        return item

# Usage
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)

for item in stack:
    print(item)  # Output: 1, 2, 3

Para saber mais sobre iteráveis personalizados e comportamento de contêineres, consulte o Tutorial de listas do Python e o Tutorial e exemplos de funções e métodos de listas do Python.

Práticas recomendadas com os métodos Dunder

É essencial saber quando e como substituir os métodos do dunder. Aqui estão algumas diretrizes que você deve ter em mente:

Quando substituir

Substitua os métodos do dunder somente se você precisar personalizar o comportamento. Por exemplo, se você quiser que seus objetos suportem verificações aritméticas ou de igualdade de uma maneira específica, vale a pena implementar métodos como __add__ ou __eq__.

Consistência

Se você substituir um método, como __eq__ para verificações de igualdade, atualize os métodos relacionados, como __hash__, de acordo. Essa consistência garante que seus objetos se comportem corretamente em coleções como conjuntos ou dicionários.

Evite o uso excessivo

Resista à tentação de criar novos nomes de dunder fora do modelo de dados padrão do Python. Se você se ater ao conjunto integrado de métodos dunder, manterá seu código claro e evitará comportamentos inesperados.

Considerações sobre o desempenho

Lembre-se de que substituir excessivamente os métodos dunder, especialmente em partes do seu código que são executadas com frequência, pode afetar o desempenho. Busque implementações eficientes para evitar lentidão em operações de alta frequência.

Conclusão e recursos adicionais

Os métodos Dunder permitem que suas classes Python interajam perfeitamente com os recursos internos da linguagem, tornando seu código mais limpo e intuitivo. Eles permitem que seus objetos lidem com tudo, desde aritmética e comparações até o gerenciamento de atributos personalizados, sem que você precise fazer um esforço extra. Você deve experimentar esses métodos em seus projetos e ver como eles podem simplificar operações complexas.

Para obter informações mais detalhadas, consulte a documentação oficial do modelo de dados Python. Você também achará úteis nossos recursos do DataCamp:


Oluseye Jeremiah's photo
Author
Oluseye Jeremiah
LinkedIn

Escritor técnico especializado em IA, ML e ciência de dados, tornando ideias complexas claras e acessíveis.

Temas

Aprenda Python com a DataCamp

Curso

Intermediate Python

4 hr
1.2M
Level up your data science skills by creating visualizations using Matplotlib and manipulating DataFrames with pandas.
Ver DetalhesRight Arrow
Iniciar curso
Ver maisRight Arrow
Relacionado

Tutorial

Função do sublinhado (_) no tutorial de Python

Neste tutorial, você aprenderá sobre os usos do sublinhado (_) em python.
Hafeezul Kareem Shaik's photo

Hafeezul Kareem Shaik

8 min

Tutorial

Tutorial de Python

Em Python, tudo é objeto. Números, cadeias de caracteres (strings), DataFrames, e até mesmo funções são objetos. Especificamente, qualquer coisa que você usa no Python tem uma classe, um modelo associado por trás.
DataCamp Team's photo

DataCamp Team

3 min

Tutorial

Programação orientada a objetos em Python (OOP): Tutorial

Aborde os fundamentos da programação orientada a objetos (OOP) em Python: explore classes, objetos, métodos de instância, atributos e muito mais!
Théo Vanderheyden's photo

Théo Vanderheyden

12 min

Tutorial

Operadores em Python

Este tutorial aborda os diferentes tipos de operadores em Python, sobrecarga de operadores, precedência e associatividade.
Théo Vanderheyden's photo

Théo Vanderheyden

9 min

Tutorial

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

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

Abid Ali Awan

7 min

Tutorial

Tutorial de docstrings em Python

Saiba mais sobre os Docstrings do Python. Encontre diferentes exemplos e tipos de formatos de docstrings para Sphinx, Numpy e Pydoc.
Aditya Sharma's photo

Aditya Sharma

15 min

Ver maisVer mais