IOKELU
Nivel: Avanzado – Guía 2
💡 Prueba el código:
Puedes ejecutar cualquier ejemplo en nuestra consola interactiva: Abrir consola de Python →

Decoradores avanzados en Python

Los decoradores permiten modificar el comportamiento de funciones y métodos sin alterar su código interno. En esta guía aprenderás técnicas avanzadas como decoradores con argumentos, stacking, preservación de metadatos, decoradores para clases y patrones profesionales usados en proyectos reales.

Tabla de contenidos

  • Decoradores con argumentos
  • Decoradores anidados (stacking)
  • functools.wraps
  • Decoradores para métodos
  • Decoradores para clases
  • Decoradores parametrizados profesionales
  • Ejercicios
  • Mini‑proyecto

1. Decoradores con argumentos

Un decorador puede recibir parámetros si se encapsula en una función externa.

def repetir(n):
    def decorador(func):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                func(*args, **kwargs)
        return wrapper
    return decorador

@repetir(3)
def saludar():
    print("Hola")

saludar()

2. Decoradores anidados (stacking)

Puedes aplicar varios decoradores a una misma función.

def mayus(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs).upper()
    return wrapper

def exclamacion(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs) + "!"
    return wrapper

@mayus
@exclamacion
def mensaje():
    return "hola"

print(mensaje())

3. functools.wraps

wraps preserva el nombre y docstring de la función original.

from functools import wraps

def log(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print("Ejecutando:", func.__name__)
        return func(*args, **kwargs)
    return wrapper

@log
def sumar(a, b):
    """Suma dos números."""
    return a + b

print(sumar.__name__)
print(sumar.__doc__)

4. Decoradores para métodos

def verificar_login(func):
    def wrapper(self, *args, **kwargs):
        if not self.logueado:
            raise PermissionError("Usuario no logueado")
        return func(self, *args, **kwargs)
    return wrapper

class Usuario:
    def __init__(self):
        self.logueado = False

    @verificar_login
    def acceder(self):
        return "Acceso permitido"

5. Decoradores para clases

Un decorador puede modificar o extender una clase completa.

def agregar_repr(cls):
    def __repr__(self):
        return f"{cls.__name__}({self.__dict__})"
    cls.__repr__ = __repr__
    return cls

@agregar_repr
class Punto:
    def __init__(self, x, y):
        self.x = x
        self.y = y

print(Punto(3, 4))

6. Decoradores parametrizados profesionales

def validar_tipo(tipo):
    def decorador(func):
        def wrapper(valor):
            if not isinstance(valor, tipo):
                raise TypeError("Tipo incorrecto")
            return func(valor)
        return wrapper
    return decorador

@validar_tipo(int)
def cuadrado(n):
    return n * n

7. Ejercicios

8. Mini‑proyecto: Sistema de logging avanzado

def logger(nombre):
    def decorador(func):
        def wrapper(*args, **kwargs):
            print(f"[{nombre}] Ejecutando {func.__name__}")
            return func(*args, **kwargs)
        return wrapper
    return decorador

@logger("DB")
def conectar():
    return "Conectado"

print(conectar())

Siguiente guía

Generadores avanzados →