ParamSpec en Python: Decorators con Tipado resuelve un problema frecuente en proyectos Python: Reenvía la firma completa de una callable mediante una función de orden superior. Esta guía explica el mecanismo, presenta un ejemplo ejecutable y marca los límites que evitan una implementación frágil.

Concepto y caso de uso

ParamSpec captura parámetros posicionales y nombrados; TypeVar captura el retorno. Juntos conservan la relación entre función recibida y devuelta.

Para repasar los fundamentos relacionados, consulta también la guía de type hints. La integración es más simple cuando cada función recibe dependencias y datos explícitamente en lugar de depender de estado global.

Ejemplo práctico

from collections.abc import Callable
from functools import wraps
from typing import ParamSpec, TypeVar

P = ParamSpec("P")
R = TypeVar("R")

def traced(func: Callable[P, R]) -> Callable[P, R]:
    @wraps(func)
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
        print(func.__name__)
        return func(*args, **kwargs)
    return wrapper

Usa functools.wraps para metadatos runtime y Callable[P, R] para el contrato estático. Concatenate sirve si se añade un argumento inicial.

Decisiones importantes

La elección correcta depende del contrato público, del volumen y del comportamiento ante fallos.

Considera concurrencia, entradas vacías y fallos parciales. Documenta cada límite que afecte a consumidores y usa nombres que expresen intención.

Errores frecuentes

El ejemplo mínimo no sustituye límites, manejo de errores y observabilidad. Callable[..., R] pierde la comprobación de argumentos. ParamSpec no conserva nombre, documentación ni introspección por sí solo.

Evita capturar excepciones sin contexto o devolver resultados parciales como si fueran completos. Un fallo explícito suele ser más seguro que datos silenciosamente incorrectos.

Cómo validar

Valida el comportamiento y no solo el camino feliz. Ejecuta el type checker con firmas distintas y comprueba autocompletado, argumentos rechazados y retorno inferido.

La documentación oficial, consultada el 28 de julio de 2026, detalla la API y debe ser la referencia para cambios futuros.