O que são decorators e por que usá-los?
Um decorator é uma função que modifica outra função ou método. Ele permite adicionar comportamento sem alterar o código original. Por exemplo, você pode medir tempo de execução ou verificar permissões. Essa técnica é comum em Python e TypeScript. Assim, o código fica mais limpo e reutilizável.Decorator de logging para rastrear execução
O logging ajuda a depurar e monitorar aplicações. Primeiramente, crie um decorator que registra nome e argumentos da função. Em seguida, ele imprime uma mensagem antes e depois da execução. Por exemplo:|
1 2 3 4 5 6 7 |
def log(func): def wrapper(*args, **kwargs): print(f"Chamando {func.__name__}") resultado = func(*args, **kwargs) print(f"{func.__name__} terminou") return resultado return wrapper |
Cache com decorators para otimizar performance
Cache evita recálculos desnecessários de funções pesadas. Um exemplo clássico é o@lru_cache da biblioteca functools.
Ele guarda resultados com base nos argumentos fornecidos.
Assim, chamadas repetidas retornam instantaneamente.
Porém, cuidado com funções que dependem de dados mutáveis.
Aqui está um exemplo manual simples:
|
1 2 3 4 5 6 7 |
def cache(func): armazenamento = {} def wrapper(arg): if arg not in armazenamento: armazenamento[arg] = func(arg) return armazenamento[arg] return wrapper |
Decorator de autenticação para controle de acesso
Autenticação verifica se um usuário tem permissão para executar algo. Por exemplo, um decorator pode checar um token antes da execução. Se o token for inválido, uma exceção é levantada. Caso contrário, a função original roda normalmente. Isso é comum em rotas de APIs web. Veja um esboço:|
1 2 3 4 5 6 |
def autenticar(func): def wrapper(usuario, *args, **kwargs): if not usuario.get("autenticado"): raise PermissionError("Acesso negado") return func(usuario, *args, **kwargs) return wrapper |
Como combinar múltiplos decorators
Frequentemente, você precisará aplicar mais de um decorator na mesma função. Eles são aplicados de baixo para cima na sintaxe. Portanto,@log @cache significa cache primeiro, depois log.
Essa ordem pode ser alterada conforme a necessidade.
Tenha cuidado para não criar interdependências ocultas.
Boas práticas e considerações finais
Decore funções pequenas e bem definidas para evitar confusão. Os decorators podem ser empilhados, mas a ordem importa. Teste sempre cada decorator isoladamente. Além disso, usefunctools.wraps para preservar metadados da função original.
Isso evita surpresas com nomes ou docstrings.
Com essas ferramentas, seu código ganha transparência e eficiência.
Portanto, experimente aplicá-las em projetos reais.