Decoradores @ em Python: Guia Prático e Exemplos

Decoradores em Python são uma ferramenta poderosa para modificar o comportamento de funções ou classes. O símbolo @ é usado para aplicar um decorador de forma sintática.

Quando você escreve:

@decorador2
@decorador1
def minha_funcao(arg1, arg2):
    pass

Isso é equivalente a:

def minha_funcao(arg1, arg2):
    pass
minha_funcao = decorador2(decorador1(minha_funcao))

A seguir, exploramos diversos casos de uso com exemplos práticos.

1. Registrar uma Função para Execução ao Sair

Este decorador registra uma função para ser chamada quando o programa termina, usando o módulo atexit.

import atexit

def registrar_saida(func):
    atexit.register(func)
    return func

@registrar_saida
def ao_sair():
    print("Executando limpeza antes de sair...")

2. Implementar uma Classe Singleton

O decorador singleton garante que apenas uma instância da classe seja criada, armazenando-a em um cache.

def singleton(cls):
    cache = {}
    def obter_instancia():
        if cls not in cache:
            cache[cls] = cls()
        return cache[cls]
    return obter_instancia

@singleton
class MinhaClasse:
    def __init__(self):
        self.dado = "Única instância"

3. Adicionar Atributos a uma Função

Este decorador permite definir atributos personalizados em funções, como versão ou autor.

def adicionar_atributos(**atributos):
    def decorador(func):
        for chave, valor in atributos.items():
            setattr(func, chave, valor)
        return func
    return decorador

@adicionar_atributos(versao="1.0", autor="Ana Silva")
def meu_metodo():
    pass

print(meu_metodo.versao)  # Saída: 1.0

4. Verificar Tipos de Argumentos e Retorno

Decoradores para validar os tipos dos argumentos e do valor de retorno de uma função.

def aceita_tipos(*tipos):
    def verificar(func):
        def nova_func(*args, **kwargs):
            for arg, tipo in zip(args, tipos):
                if not isinstance(arg, tipo):
                    raise TypeError(f"Argumento {arg} não é do tipo {tipo}")
            return func(*args, **kwargs)
        nova_func.__name__ = func.__name__
        return nova_func
    return verificar

def retorna_tipo(tipo_retorno):
    def verificar(func):
        def nova_func(*args, **kwargs):
            resultado = func(*args, **kwargs)
            if not isinstance(resultado, tipo_retorno):
                raise TypeError(f"Retorno {resultado} não é do tipo {tipo_retorno}")
            return resultado
        nova_func.__name__ = func.__name__
        return nova_func
    return verificar

@aceita_tipos(int, float)
@retorna_tipo(float)
def multiplicar(a, b):
    return a * b

5. Declarar Conformidade com Interfaces

Este exemplo demonstra como usar decoradores para indicarr que uma classe implementa uma interface específica.

class InterfaceExemplo:
    pass

def implementa(*interfaces):
    def decorador(classe):
        # Lógica para registrar conformidade (exemplo simplificado)
        classe._interfaces = interfaces
        return classe
    return decorador

@implementa(InterfaceExemplo)
class MinhaClasse2:
    def metodo(self):
        pass

Tags: Python decoradores @decorator sintaxe Python programação avançada

Publicado em 6-2 18:44 por Thomas