Como usar decoradores Python para aprimorar funções
Decoradores Python são uma maneira poderosa e flexível de modificar ou aprimorar funções e métodos. Decoradores fornecem uma maneira de encapsular uma função com funcionalidade adicional, permitindo que você estenda seu comportamento sem modificar seu código real. Este artigo apresentará a você o conceito de decoradores, como criá-los e usá-los, e explorará alguns exemplos práticos.
O que é um decorador?
Um decorador é uma função que pega outra função e estende seu comportamento sem modificá-la explicitamente. Em Python, decoradores são frequentemente usados para adicionar funcionalidades como registro, controle de acesso ou medição de desempenho a funções ou métodos existentes. Decoradores são aplicados a funções usando a sintaxe @decorator_name
.
# Basic example of a decorator
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Como os decoradores trabalham
Quando você aplica um decorador a uma função, o Python basicamente executa as seguintes etapas:
- A função decoradora é chamada com a função original como argumento.
- A função decoradora define uma nova função (geralmente chamada de
wrapper
) que aprimora ou modifica o comportamento da função original. - A função decoradora retorna a nova função.
- Quando a função decorada é chamada, ela na verdade chama a nova função retornada pelo decorador.
Criando um decorador simples
Vamos criar um decorador simples que mede o tempo de execução de uma função. Isso é útil para testes de desempenho e otimização.
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Execution time: {end_time - start_time} seconds")
return result
return wrapper
@timing_decorator
def slow_function():
time.sleep(2)
print("Function finished!")
slow_function()
Usando decoradores com argumentos
Às vezes, você pode querer passar argumentos para seu decorador. Para conseguir isso, você precisa criar uma fábrica de decoradores — uma função que retorna um decorador. Aqui está um exemplo de um decorador que recebe um argumento para especificar uma mensagem personalizada.
def custom_message_decorator(message):
def decorator(func):
def wrapper(*args, **kwargs):
print(message)
return func(*args, **kwargs)
return wrapper
return decorator
@custom_message_decorator("Starting the function...")
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
Decoradores para métodos em classes
Decoradores também podem ser usados com métodos dentro de classes. Usos comuns incluem registro de chamadas de método, controle de acesso e resultados de cache. Aqui está um exemplo de uso de um decorador para registrar chamadas de método em uma classe.
def log_method_call(method):
def wrapper(self, *args, **kwargs):
print(f"Calling {method.__name__} with arguments {args} and keyword arguments {kwargs}")
return method(self, *args, **kwargs)
return wrapper
class MyClass:
@log_method_call
def my_method(self, x, y):
print(f"Result: {x + y}")
obj = MyClass()
obj.my_method(5, 7)
Decoradores de correntes
Você pode aplicar vários decoradores a uma única função. Eles são aplicados do decorador mais interno ao mais externo. Isso permite que você componha diferentes funcionalidades juntas. Aqui está um exemplo de encadeamento de dois decoradores:
def uppercase_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
def exclamation_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + "!"
return wrapper
@exclamation_decorator
@uppercase_decorator
def greet(name):
return f"Hello, {name}"
print(greet("Alice"))
Conclusão
Decoradores são uma ferramenta versátil em Python que permite que você aprimore ou modifique o comportamento de funções e métodos. Ao usar decoradores, você pode adicionar funcionalidade reutilizável em sua base de código sem alterar a lógica central de suas funções. Seja para registro, temporização ou modificação de saída, os decoradores ajudam a manter seu código limpo e sustentável. Pratique o uso de decoradores para se tornar mais proficiente e alavancar seu poder em seus projetos Python.