CodeGym /Cursos /Python SELF ES /Toda la potencia de los decoradores

Toda la potencia de los decoradores

Python SELF ES
Nivel 14 , Lección 2
Disponible

6.1 Decoradores para métodos de clase

Los decoradores también pueden utilizarse para métodos de clase. Es importante recordar que para los métodos de clase es necesario pasar correctamente los argumentos self o cls.

Aún no hemos cubierto en detalle el funcionamiento de las clases, pero me gustaría que supieras que existe tal posibilidad para los decoradores.


def log_method_call(func):
    def wrapper(self, *args, **kwargs):
        print(f"Llamada al método {func.__name__}")
        return func(self, *args, **kwargs)

    return wrapper
        
class MyClass:
    @log_method_call
    def say_hello(self):
        print("Hello from MyClass!")
        
obj = MyClass()
obj.say_hello()

Explicación

Decorador (log_method_call): Este decorador toma el método func y devuelve una nueva función wrapper que imprime un mensaje antes de la llamada al método.

Método de clase con decorador (say_hello): El método say_hello está envuelto con el decorador log_method_call, lo que añade un comportamiento adicional al ser llamado.

Salida:


Llamada al método say_hello
Hello from MyClass!

6.2 Varios decoradores

Puedes usar varios decoradores para una función, aplicándolos en capas uno sobre otro. Los decoradores se aplican en el orden inverso a su declaración.


def decorator1(func):
    def wrapper():
        print("Decorador 1")
        func()

    return wrapper
        
def decorator2(func):
    def wrapper():
        print("Decorador 2")
        func()

    return wrapper
        
@decorator1
@decorator2
def say_hello():
    print("Hello!")
        
say_hello()

Explicación

Decoradores (decorator1 y decorator2): Estos decoradores añaden sus mensajes antes de la llamada a la función func.

Función con decoradores (say_hello): La función say_hello está envuelta con ambos decoradores. Primero se aplica decorator2, luego decorator1.

Salida:


# Decorador 1
# Decorador 2
Hello!

6.3 Decoradores integrados

Python proporciona varios decoradores integrados para tareas estándar, como métodos estáticos, métodos de clase y propiedades.

@staticmethod

El decorador @staticmethod se utiliza para crear un método estático, que no requiere una instancia de la clase para ser llamado.


class MyClass:
    @staticmethod
    def static_method():
        print("Este es un método estático.")
        
MyClass.static_method()

@classmethod

El decorador @classmethod se utiliza para crear un método de clase, que toma la clase (en lugar de la instancia) como primer argumento.


class MyClass:
    @classmethod
    def class_method(cls):
        print(f"Este es un método de clase {cls.__name__}.")
        
MyClass.class_method()

@property

El decorador @property se utiliza para crear getters, setters y deleters para atributos.


class MyClass:
    def __init__(self, value):
        self.hidden_value = value
        
    @property
    def value(self):
        return self.hidden_value
        
    @value.setter
    def value(self, new_value):
        self.hidden_value = new_value
        
obj = MyClass(10)
print(obj.value)  # Salida: 10
obj.value = 20
print(obj.value)  # Salida: 20

Estos son decoradores integrados y su funcionamiento correcto es gestionado por el propio intérprete de Python.

6.4 Ejemplos de uso de decoradores

Logging

Los decoradores pueden ser utilizados para hacer logging de las llamadas a funciones y métodos.


def log_call(func):
    def wrapper(*args, **kwargs):
        print(f"Llamada a la función {func.__name__} con argumentos {args} y {kwargs}")
        return func(*args, **kwargs)

    return wrapper
        
@log_call
def add(x, y):
    return x + y
        
print(add(2, 3))

Control de acceso

Los decoradores pueden ser utilizados para el control de acceso a funciones y métodos.


def require_authentication(func):
    def wrapper(*args, **kwargs):
        if not args[0].is_authenticated:
            raise PermissionError("Usuario no autenticado.")
        return func(*args, **kwargs)
        
    return wrapper
        
class User:
    def __init__(self, is_authenticated):
        self.is_authenticated = is_authenticated
        
    @require_authentication
    def view_profile(self):
        print("Perfil del usuario")
        
user = User(is_authenticated=True)
user.view_profile()  # Llamada exitosa
        
user2 = User(is_authenticated=False)
user2.view_profile()  # PermissionError: Usuario no autenticado.

Cacheo

Los decoradores pueden ser utilizados para cachear los resultados de una función.


def cache(func):
    cached_results = {}

    def wrapper(*args):
        if args in cached_results:
            return cached_results[args]
        result = func(*args)
        cached_results[args] = result
        return result

    return wrapper

@cache
def fib(n):
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(35))
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION