[PYTHON] Usando funções decoradoras (Decorators)
Saudações!
Recentemente estava eu me aventurando com Flask e notei que poderia ser usado um @login_required junto com alguma rota da aplicação e fiquei curioso sobre o funcionamento
Que tal ver como funcionam esses famosos @'s que podemos adicionar uma linha antes da nossas funções em python?
Bora lá!
Antes de tudo a PEP 318 fala muita coisa sobre decoradores para funções e métodos e ainda tem alguns exmplos bem da hora, vale dar uma olhadinha 😉
Em Python, os decoradores são uma forma poderosa de modificar ou estender o comportamento de funções ou métodos sem alterar seu código interno. 🚀🚀
Eles são aplicados usando a sintaxe @decorador acima da definição da sua função, desse jeito.
@meu_decorador
def minha_função ():
#código
O decorador é, na verdade, uma função que recebe outra função como argumento e retorna uma nova função que geralmente estende ou modifica o comportamento da função original. 🤖
Doido, não?! Relaxa, é muito simples, saca esse exemplo!
# Exemplo de um decorador simples
def meu_decorador(funcao):
def wrapper():
print("Antes da execução da função.")
resultado = funcao()
print("Depois da execução da função.")
return resultado
return wrapper
@meu_decorador
def minha_funcao():
print("Executando minha função.")
# Chamando a função decorada
minha_funcao()
Execução do código:
Antes da execução da função.
Executando minha função.
Depois da execução da função.
Neste exemplo, @meu_decorador é um decorador que envolve a função minha_funcao com funcionalidades adicionais. Quando chamamos minha_funcao(), o decorador é aplicado automaticamente.
O que acontece nos bastidores é que a função minha_funcao é passada como argumento para a função meu_decorador, e o decorador retorna uma nova função chamada wrapper. Essa nova função inclui o código adicional (como por exemplo imprimir mensagens antes e depois da execução da função original) e, em seguida, chama a função original (funcao()).
É importante notar que, ao usar o decorador com @meu_decorador acima da definição da função, você está essencialmente dizendo que deseja que minha_funcao seja envolvida pelo meu_decorador antes de ser chamada.
UAU! certo? mas e se você precisar passar parâmetros?
Você pode fazer isso utilizando os *args e **kwargs na função wrapper e passá-los na chamada da função que foi decorada, simples assim!
# Exemplo de um decorador simples com parâmetros
def meu_decorador(funcao):
def wrapper(*args, **kwargs): # <------ Parâmetros para a função
print("Antes da execução da função.")
resultado = funcao(*args, **kwargs) # <------ Passagem dos parâmetros na chamada da função
print("Depois da execução da função.")
return resultado
return wrapper
@meu_decorador
def minha_funcao(nome):
print("Executando minha função.")
print(f"Olá, {nome}!")
# Chamando a função decorada
minha_funcao("João")
Execução do código:
Antes da execução da função.
Executando minha função.
Olá, João!
Depois da execução da função.
Este é um exemplo básico, mas decoradores podem ter uma variedade de aplicações e serem utilizados para tarefas como verificação de autorização, medição de tempo de execução, entre outros.
O Python possui muitos decoradores incorporados, como @staticmethod, @classmethod, e a biblioteca Flask, assim como outras fazem extenso uso de decoradores para configurar rotas, autenticação, etc.
Exemplos:
TEMPO DE EXECUÇÃO - Mede o tempo de execução da função e faz o log no terminal
import time
def medir_tempo(func):
def wrapper(*args, **kwargs):
inicio = time.time()
resultado = func(*args, **kwargs)
fim = time.time()
print(f"{func.__name__} levou {fim - inicio} segundos para executar.")
return resultado
return wrapper
@medir_tempo
def operacao_demorada():
# Código demorado
time.sleep(2)
return "Concluído."
FLASK - Acesso de rota da aplicação somente com login efetuado, caso não esteja logado redireciona para a página de login.
from functools import wraps
from flask import g, request, redirect, url_for
# Decorador já existente na biblioteca Flask
df login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if g.user is None:
return redirect(url_for('login', next=request.url)) #<---- Redireciona para o login
return f(*args, **kwargs)
return decorated_function
Criação da rota
@app.route('/secret_page')
@login_required #<---- Exige login para acessar rota secreta
def secret_page():
pass
Referência: Documentação Flask
Deixa um like se gostou do conteúdo. ❤️