image

Access unlimited bootcamps and 650+ courses

50
%OFF
Article image
Antonio Guedes
Antonio Guedes03/07/2025 22:58
Share
Savegnago - Lógica de ProgramaçãoRecommended for youSavegnago - Lógica de Programação

Decoradores: Um bom jeito de alterar o funcionamento das funções, sem realmente alterá-las.

    Uma forma de adicionar comportamentos de funções e classes.

    O que são Decoradores?

    São funções que adicionam comportamentos às funções. Por exemplo: você quer que algo seja apresentado na tela antes da execução de sua função ou após a execução da mesma. Ou então, calcular o tempo de execução da função. Há muitas utilidades no uso de decoradores que talvez você já utiliza e nem sabe.

    Quando você cria uma classe e ao criar um método de classe você usa o decorado: @classmethod, ou para marcar propriedades da classe e usa o decorador: @property, olha os decoradores ai. Nestes casos utilizando decoradores para atributos e métodos. Há também como usar os decoradores para toda a classe. Interessente, não é?

    Uma coisa que até hoje eu não sabia é que você pode usar decoradores em funções sem argumentos, com argumentos e o mais interessante, você pode criar um decorador que funciona ao mesmo tempo em funções com e sem argumentos: 😮.

    Como assim?

    Imagine que você quer saber quando uma função é chamada, quando ela termina de ser executada e quanto tempo ela levou para ser executada.

    para isso usamos a decoradora abaixo:

    import time
    
    def log_execucao(func):
      def wrapper(*args, **kwargs):
          nome_funcao = func.__name__
          print(f"--- [LOG] Iniciando '{nome_funcao}' ---")
        
          inicio_tempo = time.perf_counter() # Marca o tempo de início
        
          #chama função original com todos os seus argumentos
          resultado = func(*args, **kwargs)
        
          fim_tempo = time.perf_counter()
          tempo_decorrido = fim_tempo - inicio_tempo
        
          print(f"--- [LOG] Finalizando '{nome_funcao}' em {tempo_decorrido:.4f} segundos ---")
        
          return resultado
      return wrapper
      
    
    # Aplicando o decorador
    
    ### Função sem argumentos
    @log_execucao
    def cumprimentar():
      print('Olá, mundo!')
    
    
    print("Chamando a função 'cumprimentar' (sem argumentos)")
    cumprimentar()
    print('\n')
    
    ### Função com argumentos posicionais
    @log_execucao
    def somar(a, b):
      print(f"Calculando {a} + {b}")
      time.sleep(0.5) # Somente pra simular um processamento
      return a + b
      
    print(f"Chamando a função 'Somar' (com agumentos posicionais)")
    soma_resultado = somar(10, 20)
    print(f"Resultado da soma: {soma_resultado}")
    print('\n')
    
    
    ### Função com Argumentos Nomeados
    @log_execucao
    def configurar(host='localhost', port=8080):
      print(f'COnfigurando servidor em: {host}:{port}...')
      time.sleep(0.2)
      return f"Serviço configurado para {host}:{port}"
    
    print(f'Chamando a função "Configurar" (com argumentos nomeados):')
    configuracao_resultado = configurar(port=3000, host='meu_servidor.com')
    print(f"Status de configuração: {configuracao_resultado}")
    print('\n')
    
    
    ### Função com ambos os tipos de argumentos
    @log_execucao
    def calcular_desconto(preco_base, percentual, cupom=None):
      desconto_valor = preco_base * (percentual / 100)
      preco_final = preco_base - desconto_valor
      if cupom:
         print(f'Aplicando cumpo: {cupom}...')
      print(f"Preço original: R${preco_base:.2f}, Desconto: {percentual}%, Preço final {preco_final:.2f}")
      return preco_final
    
    
    print('Chamando a função "calcular_desconto" (com argumentos posicionais e nomeados)')
    preco_descontado = calcular_desconto(100.00, 10, cupom='PRIMEIRACOMPRA')
    print(f"Preço após desconto: R${preco_descontado:.2f}")
    
    # Saídas
    # Chamando a função 'cumprimentar' (sem argumentos)
    # --- [LOG] Iniciando 'cumprimentar' ---
    # Olá, mundo!
    # --- [LOG] Finalizando 'cumprimentar' em 0.0001 segundos ---
    
    # Chamando a função 'Somar' (com agumentos posicionais)
    # --- [LOG] Iniciando 'somar' ---
    # Calculando 10 + 20
    # --- [LOG] Finalizando 'somar' em 0.5005 segundos ---
    # Resultado da soma: 30
    
    # Chamando a função "Configurar" (com argumentos nomeados):
    # --- [LOG] Iniciando 'configurar' ---
    # COnfigurando servidor em: meu_servidor.com:3000...
    # --- [LOG] Finalizando 'configurar' em 0.2002 segundos ---
    # Status de configuração: Serviço configurado para meu_servidor.com:3000
    
    # Chamando a função "calcular_desconto" (com argumentos posicionais e nomeados)
    # --- [LOG] Iniciando 'calcular_desconto' ---
    # Aplicando cumpo: PRIMEIRACOMPRA...
    # Preço original: R$100.00, Desconto: 10%, Preço final 90.00
    # --- [LOG] Finalizando 'calcular_desconto' em 0.0002 segundos ---
    # Preço após desconto: R$90.00
    

    Existe também a possibilidade de o próprio decorador receber um argumento.

    Imagina que neste decorador log_execucao, queiramos receber a data e o horário Da chamada da função. Então você pode receber o argumento na função externa do decorador.

    Olha como fica a funçao log_execucao:

    from datetime import datetime

    def log_execucao(data):
      def decorador_interno(func):
          def wrapper(*args, **kwargs):
              nome_funcao = func.__name__
              print(f"Data e hora da chamada: {data.strftime('%d/%m/%Y %H:%M:%S')}")
              print(f"--- [LOG] Iniciando '{nome_funcao}' ---")
              inicio_tempo = time.perf_counter() # Marca o tempo de início
             	#chama função original com todos os seus argumentos
             	resultado = func(*args, **kwargs)
              fim_tempo = time.perf_counter()
              tempo_decorrido = fim_tempo - inicio_tempo
              print(f"--- [LOG] Finalizando '{nome_funcao}' em {tempo_decorrido:.4f} segundos ---")
              return resultado
          return wrapper
      return decorador_interno
    
    
    # Criando a função decorada
    @log_execucao(datetime.now()) # Agora adicionamos argumento no decorador
    def cumprimentar():
    print('Olá, mundo!')
    
    print("Chamando a função 'cumprimentar' (sem argumentos)")
    cumprimentar()
    print('\n')
    
    # SAÍDA
    # Chamando a função 'cumprimentar' (sem argumentos)
    # Data e hora da chamada: 03/07/2025 17:56:25
    # --- [LOG] Iniciando 'cumprimentar' ---
    # Olá, mundo!
    # --- [LOG] Finalizando 'cumprimentar' em 0.0001 segundos ---
    

    Espero que meus exemplos ajudem a entender um pouco mais os decoradores de funções.

    Share
    Recommended for you
    Deal Group - AI Centric .NET
    Randstad - Análise de Dados
    BairesDev - Machine Learning Training
    Comments (1)
    Carlos Barbosa
    Carlos Barbosa - 04/07/2025 01:42

    Boa, Antonio!! 🚀

    Recommended for youSavegnago - Lógica de Programação