Article image
Mateus Konkol
Mateus Konkol08/01/2024 10:07
Compartilhe

Funções em 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. 🤖

    image

    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.

    image

    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
    def 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

    image

    Deixa um like se gostou do conteúdo. ❤️

    Compartilhe
    Comentários (0)