Decoradores em Python: o que são, como funcionam e para que servem

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

O que são decoradores em Python

Se você programa em Python há mais de uma semana, certamente já viu o símbolo @ acima de uma função. Isso é um decorador — uma ferramenta poderosa e elegante de programação.

Decoradores em Python permitem "encapsular" uma função dentro de outra. Eles modificam ou estendem o comportamento de uma função sem alterar seu código original. Decoradores são usados em toda parte: em Flask, Django, FastAPI, pytest, e até mesmo na biblioteca padrão do Python.

Como os decoradores funcionam

Fundamentos dos decoradores

Um decorador é uma função que recebe outra função como argumento e retorna uma nova função (ou a função original modificada).

def decorator(func):
    def wrapper():
        print("Antes da chamada")
        func()
        print("Depois da chamada")
    return wrapper

@decorator
def say_hello():
    print("Olá!")

say_hello()

Resultado da execução:

Antes da chamada
Olá!
Depois da chamada

O símbolo @decorator é um açúcar sintático para a escrita:

say_hello = decorator(say_hello)

Funcionamento interno dos decoradores

Para entender decoradores em Python, é preciso conhecer alguns conceitos-chave:

  • Em Python, funções são objetos de primeira classe
  • Funções podem ser passadas como argumentos para outras funções
  • É possível definir funções dentro de outras funções
  • Existe o mecanismo de closures (encerramentos)

Modelo universal de decorador

O modelo mínimo de um decorador é o seguinte:

def decorator(func):
    def wrapper(*args, **kwargs):
        # Ações antes da execução da função
        result = func(*args, **kwargs)
        # Ações depois da execução da função
        return result
    return wrapper

Exemplos práticos de decoradores

Decorador para medir tempo de execução

import time

def timing(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        execution_time = time.time() - start
        print(f"{func.__name__} levou {execution_time:.4f} segundos")
        return result
    return wrapper

@timing
def slow_func():
    time.sleep(1)
    return "Operação concluída"

slow_func()

Este decorador é útil para analisar o desempenho de funções e otimizar seu código.

Decorador de verificação de autorização

def require_admin(func):
    def wrapper(user, *args, **kwargs):
        if user != "admin":
            raise PermissionError("Acesso negado")
        return func(user, *args, **kwargs)
    return wrapper

@require_admin
def delete_database(user):
    print("Banco de dados excluído!")
    return True

delete_database("admin")  # Execução bem-sucedida

Esse decorador garante a segurança da aplicação, controlando o acesso a funções críticas.

Decorador de logging

import logging
from functools import wraps

def log_calls(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        logging.info(f"Chamada da função {func.__name__} com argumentos {args}, {kwargs}")
        try:
            result = func(*args, **kwargs)
            logging.info(f"Função {func.__name__} executada com sucesso")
            return result
        except Exception as e:
            logging.error(f"Erro na função {func.__name__}: {e}")
            raise
    return wrapper

Decoradores com argumentos

Criando uma fábrica de decoradores

Quando um decorador precisa receber parâmetros, cria-se uma fábrica de decoradores:

def repeat(n):
    def decorator(func):
        def wrapper(*args, **kwargs):
            results = []                

Blogs

Book Recommendations