Cómo utilizar decoradores de Python para mejorar funciones
Los decoradores de Python son una forma potente y flexible de modificar o mejorar funciones y métodos. Los decoradores proporcionan una forma de envolver una función con funcionalidad adicional, lo que le permite extender su comportamiento sin modificar su código real. Este artículo le presentará el concepto de decoradores, cómo crearlos y usarlos, y explorará algunos ejemplos prácticos.
¿Qué es un Decorador?
Un decorador es una función que toma otra función y extiende su comportamiento sin modificarla explícitamente. En Python, los decoradores se utilizan a menudo para añadir funcionalidades como registro, control de acceso o medición del rendimiento a funciones o métodos existentes. Los decoradores se aplican a funciones mediante la sintaxis @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()
Cómo trabajan los decoradores
Cuando se aplica un decorador a una función, Python esencialmente realiza los siguientes pasos:
- La función decoradora se llama con la función original como argumento.
- La función decoradora define una nueva función (a menudo llamada
wrapper
) que mejora o modifica el comportamiento de la función original. - La función decoradora devuelve la nueva función.
- Cuando se llama a la función decorada, en realidad llama a la nueva función devuelta por el decorador.
Creando un decorador simple
Creemos un decorador simple que mida el tiempo de ejecución de una función. Esto resulta útil para pruebas de rendimiento y optimización.
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()
Uso de decoradores con argumentos
A veces, es posible que desees pasar argumentos a tu decorador. Para lograrlo, debes crear una fábrica de decoradores, una función que devuelve un decorador. Aquí tienes un ejemplo de un decorador que toma un argumento para especificar un mensaje personalizado.
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 en clases
Los decoradores también se pueden utilizar con métodos dentro de las clases. Los usos más comunes incluyen el registro de llamadas a métodos, el control de acceso y el almacenamiento en caché de resultados. A continuación, se muestra un ejemplo de uso de un decorador para registrar llamadas a métodos en una clase.
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)
Encadenamiento de decoradores
Puedes aplicar varios decoradores a una sola función. Se aplican desde el decorador más interno al más externo. Esto te permite componer diferentes funcionalidades juntas. Aquí tienes un ejemplo de encadenamiento de dos 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"))
Conclusión
Los decoradores son una herramienta versátil en Python que le permite mejorar o modificar el comportamiento de las funciones y los métodos. Al utilizar decoradores, puede agregar funcionalidad reutilizable a su código base sin cambiar la lógica central de sus funciones. Ya sea para registrar, cronometrar o modificar la salida, los decoradores ayudan a mantener su código limpio y fácil de mantener. Practique el uso de decoradores para volverse más competente y aprovechar su poder en sus proyectos de Python.