Fundamentos de Decoradores em Python

PythonBeginner
Pratique Agora

Introdução

Decoradores em Python permitem modificar ou aprimorar o comportamento de uma função, classe ou método. Eles são uma forma de alterar dinamicamente a funcionalidade do seu código sem mudar o código-fonte. Neste laboratório, exploraremos os fundamentos dos decoradores e como usá-los para adicionar funcionalidade ao seu código.

Entendendo Decoradores

Vamos começar com um exemplo simples. Abra uma nova sessão do interpretador Python:

python3

Temos uma função que calcula o quadrado de um número:

def square(x):
    return x**2

Agora, digamos que queremos adicionar um recurso à função square que registra a entrada e a saída da função toda vez que ela é chamada. Podemos fazer isso usando um decorador.

Aqui está o código para o decorador logger:

def logger(func):
    def wrapper(x):
        print("Calling function:", func.__name__)
        print("Input:", x)
        result = func(x)
        print("Output:", result)
        return result
    return wrapper

Agora podemos usar este decorador para aprimorar a função square:

@logger
def square(x):
    return x**2

Quando chamamos square(5), a saída será:

Calling function: square
Input: 5
Output: 25

Como pode ver, o decorador adicionou a funcionalidade desejada à função square sem alterar seu código-fonte.

Decoradores com Parâmetros

Decoradores também podem aceitar parâmetros. Por exemplo, poderíamos modificar o decorador logger para aceitar uma mensagem a ser impressa antes dos registros de entrada e saída.

def logger(message):
    def decorator(func):
        def wrapper(x):
            print(message)
            print("Calling function:", func.__name__)
            print("Input:", x)
            result = func(x)
            print("Output:", result)
            return result
        return wrapper
    return decorator

Agora podemos usar este decorador atualizado para aprimorar a função square:

@logger("This is a custom message")
def square(x):
    return x**2

Quando chamamos square(5), a saída será:

This is a custom message
Calling function: square
Input: 5
Output: 25

Usando Múltiplos Decoradores

Você também pode empilhar múltiplos decoradores uns sobre os outros para adicionar múltiplos níveis de funcionalidade. Por exemplo, vamos criar um novo decorador chamado timer que mede o tempo que uma função leva para ser executada:

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print("Time elapsed:", end_time - start_time)
        return result
    return wrapper

Agora vamos usar os decoradores logger e timer na função square:

@logger("This is a custom message")
@timer
def square(x):
    return x**2

Quando chamamos square(5), a saída será:

This is a custom message
Calling function: square
Input: 5
Output: 25
Time elapsed: 0.000001

Como pode ver, o decorador timer adicionou a informação de tempo decorrido à função square, enquanto o decorador logger adicionou os registros de entrada e saída e a mensagem personalizada.

Resumo

Neste laboratório, aprendemos os fundamentos dos decoradores em Python. Vimos como usar decoradores para modificar o comportamento de uma função, classe ou método, e como usar múltiplos decoradores para adicionar múltiplos níveis de funcionalidade. Também vimos como usar decoradores com parâmetros para adicionar funcionalidade personalizada.

Com estas habilidades, você pode agora começar a incorporar decoradores em seu código para tornar sua vida como desenvolvedor mais fácil!