Decoradores

Decoradores são uma das características mais elegantes e poderosas de Python. Eles permitem modificar o comportamento de funções ou métodos sem alterar o código da função em si. Decoradores são amplamente utilizados para adicionar funcionalidades, realizar verificações ou até mesmo para modificar a interface de uma função. Vamos mergulhar neste conceito e ver como podemos utilizá-los de maneira prática.

Conceito Básico

Um decorador em Python é, basicamente, uma função que recebe outra função como argumento e devolve uma nova função. Isso permite "decorar" ou adicionar funcionalidades à função original.

Estrutura Básica de um Decorador

Vamos criar um decorador simples que imprime uma mensagem antes e depois de chamar a função original.

def meu_decorador(funcao):
    def wrapper():
        print("Algo a fazer antes de executar a função.")
        funcao()
        print("Algo a fazer depois de executar a função.")
    return wrapper

Agora, podemos usar este decorador para decorar qualquer função. Por exemplo:

@meu_decorador
def diga_ola():
    print("Olá!")

diga_ola()

A saída será:

Algo a fazer antes de executar a função.
Olá!
Algo a fazer depois de executar a função.
Decoradores com Argumentos

Frequentemente, as funções que queremos decorar têm argumentos. Vamos modificar nosso decorador para aceitar qualquer número de argumentos e parâmetros.

def meu_decorador(funcao):
    def wrapper(*args, **kwargs):
        print("Algo a fazer antes de executar a função.")
        resultado = funcao(*args, **kwargs)
        print("Algo a fazer depois de executar a função.")
        return resultado
    return wrapper

Agora, vamos decorar uma função com argumentos:

@meu_decorador
def soma(a, b):
    return a + b

resultado = soma(5, 3)
print("Resultado:", resultado)

A saída agora será:

Algo a fazer antes de executar a função.
Algo a fazer depois de executar a função.
Resultado: 8

Decoradores na Vida Real

Vamos explorar alguns exemplos práticos onde decoradores são usados no dia-a-dia dos programadores.

Temporização de Funções

Imagine que quer medir quanto tempo uma função demora a executar. Um decorador é uma excelente maneira de o fazer.

import time

def temporizador(funcao):
    def wrapper(*args, **kwargs):
        inicio = time.time()
        resultado = funcao(*args, **kwargs)
        fim = time.time()
        print(f"Tempo de execução: {fim - inicio:.4f} segundos")
        return resultado
    return wrapper

@temporizador
def soma_lenta(a, b):
    time.sleep(2)
    return a + b

resultado = soma_lenta(5, 3)
print("Resultado:", resultado)

A saída será algo como:

Tempo de execução: 2.0024 segundos
Resultado: 8
Verificação de Permissões

Suponhamos que temos diferentes níveis de permissão para executar certas funções. Podemos criar um decorador para verificar permissões antes de executar a função.

def verifica_permissao(nivel_necessario):
    def decorador(funcao):
        def wrapper(*args, **kwargs):
            if args[0] < nivel_necessario:
                print("Permissão negada")
                return None
            return funcao(*args, **kwargs)
        return wrapper
    return decorador

@verifica_permissao(3)
def funcao_sensivel(nivel):
    print("Execução de uma função sensível")

nivel_utilizador = 2
funcao_sensivel(nivel_utilizador)

nivel_utilizador = 4
funcao_sensivel(nivel_utilizador)

A saída será:

Permissão negada
Execução de uma função sensível

Resumo

Os decoradores são uma ferramenta poderosa que permite adicionar ou modificar funcionalidades de funções de uma maneira eficiente e elegante. Eles são particularmente úteis para adicionar verificações, temporizações, ou outras funcionalidades transversais sem modificar diretamente o código original da função.

Quiz

Teste os seus conhecimentos sobre decoradores com as seguintes perguntas:

  1. O que é um decorador em Python?
  2. Como se define um decorador que aceita argumentos?
  3. Em que situações práticas podes usar decoradores?
  4. Escreva um decorador que imprime "Início" e "Fim" antes e depois de executar uma função.
  5. Como podemos utilizar decoradores para verificar permissões de utilizador antes de executar uma função?

Responder estas questões ajudará a consolidar o seu entendimento sobre decoradores em Python.

<< Métodos e atributos Índice Abstração >>