Como criar e usar decoradores em Python
Aprenda como escrever e aplicar decoradores em Python. Domine funções de encapsulamento, modificando comportamento, manipulando argumentos e preservando metadados com encapsulamentos.
Visão geral
Decoradores são um dos recursos de sintaxe mais elegantes e poderosos do Python, permitindo modificar o comportamento de uma função ou classe sem alterar permanentemente seu código. Eles são amplamente usados para questões transversais, como registrar tempos de execução, impor autenticação do usuário, armazenar resultados em cache (memoização) e auditar endpoints de API.
Nos bastidores, um decorador é uma função de ordem superior que recebe outra função como argumento, define uma função wrapper aninhada que injeta alguma lógica personalizada e retorna essa função wrapper. Python fornece uma sintaxe abreviada limpa usando o símbolo `@` para aplicar decoradores às funções, tornando-as visualmente elegantes.
Ao escrever decoradores, você normalmente desejará que a função decorada suporte qualquer número de argumentos posicionais e de palavras-chave. Você pode conseguir isso projetando a função wrapper aninhada para aceitar `*args` e `**kwargs` e passá-los para a função de destino. Além disso, você deve usar `functools.wraps` na função wrapper para preservar a documentação da função original e os metadados de nome.
Saída de código e execução
Este script demonstra como escrever um decorador de registro e agrupar uma função para inspecionar entradas, saídas e metadados.
from functools import wraps
# 1. Defining a decorator
def log_execution(func):
@wraps(func) # Preserves original function metadata
def wrapper(*args, **kwargs):
print(f"[Log] Calling function: {func.__name__} with args: {args}")
result = func(*args, **kwargs)
print(f"[Log] Finished {func.__name__}. Result: {result}")
return result
return wrapper
# 2. Applying the decorator using @ syntax
@log_execution
def add_numbers(a, b):
"""Adds two numbers and returns the sum."""
return a + b
# 3. Invoking the decorated function
sum_result = add_numbers(15, 25)
print("Sum Result:", sum_result)
# Verifying metadata preservation
print("Docstring preserved:", add_numbers.__doc__)[Log] Calling function: add_numbers with args: (15, 25)
[Log] Finished add_numbers. Result: 40
Sum Result: 40
Docstring preserved: Adds two numbers and returns the sum.Implementação passo a passo
- Defina uma função de decorador externo que receba a função de destino como argumento.
- Importe e aplique @functools.wraps(func) em sua função wrapper aninhada para proteger os metadados originais.
- Implemente wrapper(*args, **kwargs) para capturar variáveis de entrada, injetar lógica e invocar a função de destino.
- Retorne o objeto de função wrapper do bloco de cabeçalho do decorador.
- Aplique o decorador usando @decorator_name diretamente acima da assinatura da função alvo.
Perguntas frequentes
Por que @functools.wraps é necessário dentro de decoradores?
Sem wraps, a função decorada perde sua identidade original (seus atributos __name__ e __doc__ são substituídos pelos da função wrapper aninhada), o que dificulta a depuração e a introspecção do código.
Posso aplicar vários decoradores a uma única função?
Sim! Você pode encadear decoradores empilhando várias @ linhas. Python os aplica de baixo para cima (o mais próximo da definição da função é executado primeiro).
Tópicos Relacionados
Domine *args e **kwargs em Python. Aprenda como escrever funções flexíveis com argumentos posicionais e de palavras-chave dinâmicos, descompactar coleções e criar funções wrapper.
Como usar funções Lambda em PythonAprenda como usar funções lambda em Python. Domine funções anônimas, retornos de chamada embutidos e classificação de dados de listas com chaves lambda.
Recursos Python recomendados
Expanda seu conhecimento com tutoriais interativos relacionados, folhas de dicas e comparações de código.
Variáveis e tipos de dados Python explicados
Entenda as variáveis do Python e os principais tipos de dados (strings, inteiros, flutuantes, booleanos). Um guia completo para iniciantes sobre atribuição de memória em Python.
Folha de referências dos métodos do dicionário Python
Aprenda métodos de dicionário Python. Guia de referência completo para inserções, recuperações, atualizações e verificações de pares de valores-chave.
Python vs JavaScript: qual linguagem de programação é a melhor?
Uma comparação abrangente entre Python e JavaScript. Explore diferenças de sintaxe, desempenho, casos de uso (backend versus frontend) e exemplos de codificação.