dataclasses.KW_ONLY: exige argumentos con nombre

Publicado el: 08/09/2026
Tempo de leitura: 6 minutos
Desarrollador creando modelos con dataclasses.KW_ONLY en Python

dataclasses.KW_ONLY permite definir en una dataclass un punto a partir del cual los campos solo pueden proporcionarse por nombre. Esto hace que los constructores sean más legibles, evita llamadas ambiguas y facilita la evolución de APIs sin romper código existente. En lugar de depender de una larga secuencia posicional, puedes exigir que las opciones delicadas o secundarias aparezcan explícitamente.

En esta guía aprenderás cómo funciona KW_ONLY, en qué se diferencia de kw_only=True y cómo interactúa con herencia, valores predeterminados, __match_args__, pattern matching y dataclasses.replace. También veremos errores frecuentes y reglas prácticas para producción.

El problema de los argumentos posicionales

Imagina una clase de configuración con varios booleanos y números. Una llamada como Config('prod', True, False, 30) resulta difícil de interpretar sin consultar la firma. Intercambiar dos valores del mismo tipo puede no producir ninguna excepción, pero sí cambiar silenciosamente el comportamiento.

Una llamada con nombres es mucho más clara: Config('prod', debug=True, cache=False, timeout=30). El código expresa su intención y una futura reorganización de campos tiene menos posibilidades de introducir regresiones.

Cómo usar dataclasses.KW_ONLY

KW_ONLY es un marcador de tipo. Se declara un pseudocampo, normalmente llamado _, y todos los campos definidos después pasan a ser keyword-only.

from dataclasses import dataclass, KW_ONLY

@dataclass
class Servicio:
    nombre: str
    _: KW_ONLY
    timeout: int = 30
    reintentos: int = 3
    debug: bool = False

api = Servicio('pagos', timeout=10, reintentos=5)

El marcador no se almacena en la instancia, no aparece en la representación y nunca recibe un valor. Su única función es separar los campos posicionales de los campos nombrados.

La llamada Servicio('pagos', 10, 5) genera TypeError porque timeout y reintentos deben enviarse por nombre.

KW_ONLY frente a kw_only=True

La opción @dataclass(kw_only=True) convierte todos los campos en keyword-only. Es apropiada cuando ningún argumento posicional mejora la API. KW_ONLY es más selectivo: conserva unos pocos campos esenciales como posicionales y obliga a nombrar el resto.

Una regla útil es dejar como posicionales únicamente los campos que identifican claramente al objeto y que difícilmente cambiarán. Flags, límites, políticas, credenciales y opciones futuras suelen ser mejores como keyword-only.

Campos obligatorios con nombre

Los campos posteriores al marcador pueden tener valores predeterminados, pero no es obligatorio. Un campo requerido sigue siendo requerido; simplemente debe indicarse por nombre.

@dataclass
class Conexion:
    host: str
    _: KW_ONLY
    token: str
    puerto: int = 443
    verificar_tls: bool = True

c = Conexion('api.ejemplo.com', token='secreto')

Este patrón resulta especialmente útil para credenciales y opciones de seguridad. Etiquetas explícitas como token= o verificar_tls= reducen errores y facilitan la revisión del código.

Valores predeterminados y diseño

Los parámetros keyword-only no eliminan la necesidad de elegir buenos valores predeterminados. Deben ser seguros, previsibles y estar documentados. Evita valores que ejecuten trabajo, lean el entorno o compartan estado mutable. Para listas y diccionarios utiliza field(default_factory=...).

Cuando una clase acumula demasiadas opciones, conviene dividirla en dataclasses más pequeñas. KW_ONLY mejora la firma, pero no debe servir como excusa para un constructor con decenas de responsabilidades.

Herencia y orden final

Las dataclasses combinan los campos de clases base y derivadas. Por eso, con herencia la firma final puede ser menos evidente. Un marcador en la clase base define la organización de esa clase, mientras que la subclase puede introducir campos adicionales y sus propias reglas.

Comprueba la firma pública con inspect.signature:

from inspect import signature
print(signature(Servicio))

En una biblioteca, una prueba de firma ayuda a detectar cambios accidentales cuando se reordenan campos o se añade una nueva clase base.

Pattern matching y __match_args__

Los campos keyword-only no se incluyen en __match_args__. Por lo tanto, los patrones estructurales posicionales solo consideran los campos posicionales. Esto suele producir patrones más estables.

match api:
    case Servicio(nombre):
        print(nombre)

Para comprobar datos keyword-only, usa patrones por atributo: case Servicio(timeout=10). Esta forma es explícita y no depende del orden interno.

Uso de dataclasses.replace

dataclasses.replace funciona naturalmente con campos keyword-only porque los cambios se envían por nombre. Es especialmente útil con modelos inmutables declarados mediante frozen=True.

from dataclasses import replace
rapido = replace(api, timeout=5)

La función crea una nueva instancia, modifica el campo solicitado y conserva los demás valores. Así puedes realizar actualizaciones claras sin mutar el objeto original.

Ventajas en APIs públicas

Los parámetros posicionales forman parte del contrato público. Añadir un parámetro en medio de la firma puede romper llamadas antiguas o reinterpretarlas de manera peligrosa. Los campos opcionales keyword-only son más sencillos de añadir porque cada llamada los identifica por nombre.

Esto es importante en SDKs, bibliotecas internas, modelos de dominio, clientes de servicios y objetos de configuración que cambian con el tiempo. No sustituye al versionado semántico, pero reduce la cantidad de cambios que requieren una versión incompatible.

La validación sigue siendo necesaria

KW_ONLY controla la forma de la llamada, no la validez de los datos. Usa __post_init__ para las reglas del dominio.

@dataclass
class Tarea:
    nombre: str
    _: KW_ONLY
    prioridad: int = 5
    intentos: int = 3

    def __post_init__(self):
        if not 1 <= self.prioridad <= 10:
            raise ValueError('prioridad debe estar entre 1 y 10')
        if self.intentos < 0:
            raise ValueError('intentos no puede ser negativo')

La firma queda clara y la validación protege el estado. Son técnicas complementarias.

Errores frecuentes

No añadas varios marcadores KW_ONLY en una misma dataclass. Un solo límite es suficiente. Usa _ como nombre para indicar que no se trata de un dato real. Tampoco conviertas en keyword-only cada identificador simple cuando una llamada posicional breve sería natural.

Otro error es tratar keyword-only como un mecanismo de seguridad. Mejora la claridad, pero no limpia entradas, no comprueba tipos en tiempo de ejecución y no protege secretos. La validación y el almacenamiento seguro siguen siendo responsabilidades separadas.

Cómo probar el contrato

Prueba llamadas correctas con nombres y fallos esperados cuando se usan posiciones. Verifica campos obligatorios, valores predeterminados, herencia, pattern matching y replace. En paquetes públicos, comprobar la firma evita cambios accidentales de compatibilidad.

Los analizadores estáticos también entienden los parámetros keyword-only generados por dataclasses. Ejecutar mypy o Pyright ayuda a detectar llamadas incorrectas antes de llegar a producción.

Lista de buenas prácticas

Mantén uno o dos campos realmente esenciales como posicionales. Convierte opciones y flags en keyword-only. Elige valores seguros. Valida reglas en __post_init__. Prefiere modelos compuestos pequeños a un constructor gigante. Documenta los campos requeridos y prueba la firma final.

Para datos externos con validación compleja, Pydantic puede ser más adecuado. Para registros tipados y ligeros dentro de una aplicación Python, las dataclasses siguen siendo una excelente opción de la biblioteca estándar.

Lecturas relacionadas

Continúa con nuestras guías sobre typing.override en Python, StrEnum en Python, SimpleNamespace en Python y types.new_class en Python. Juntas ayudan a diseñar modelos y contratos más claros.

Consulta también la documentación oficial de dataclasses y la PEP 557.

Conclusión

dataclasses.KW_ONLY es una función pequeña con un gran efecto sobre legibilidad y compatibilidad. Conserva argumentos posicionales donde resultan naturales y exige nombres para opciones que podrían confundirse. En proyectos que evolucionan, esta separación reduce errores, mejora las revisiones y permite añadir nuevos campos opcionales con menor riesgo. Combínala con validación, pruebas de firma, análisis de tipos y documentación clara.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Equipo sincronizado representando asyncio.Barrier en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    asyncio.Barrier: sincroniza tareas por fases

    Aprende asyncio.Barrier en Python para sincronizar tareas por fases, coordinar pipelines y gestionar cancelaciones con seguridad.

    Ler mais

    Tempo de leitura: 6 minutos
    08/09/2026
    Desarrollador usando operator.methodcaller en código Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    operator.methodcaller: llama métodos en pipelines

    Aprende operator.methodcaller en Python para map, sorted, callbacks, argumentos y pipelines declarativos claros y reutilizables.

    Ler mais

    Tempo de leitura: 5 minutos
    07/09/2026
    Carpetas y directorios recorridos con pathlib.Path.walk en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pathlib.Path.walk: recorre y filtra directorios

    Aprende a recorrer directorios con pathlib.Path.walk en Python, filtrar archivos, omitir carpetas y evitar errores comunes.

    Ler mais

    Tempo de leitura: 6 minutos
    07/09/2026
    Código Python validado con enum.verify
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    enum.verify: valida reglas de Enum en Python

    Aprende enum.verify en Python para validar valores únicos, secuencias continuas y flags con nombres mediante reglas explícitas.

    Ler mais

    Tempo de leitura: 6 minutos
    06/09/2026
    Grafo de dependencias y flujo de tareas con TopologicalSorter en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    TopologicalSorter: ordena dependencias sin ciclos

    Aprende TopologicalSorter en Python para ordenar dependencias, detectar ciclos y ejecutar pipelines secuenciales o paralelos con seguridad.

    Ler mais

    Tempo de leitura: 6 minutos
    06/09/2026
    Carpetas y directorios que representan os.fwalk en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    os.fwalk en Python: recorre directorios

    Aprende os.fwalk en Python para recorrer directorios con descriptores, reducir condiciones de carrera y manipular archivos con mayor seguridad.

    Ler mais

    Tempo de leitura: 5 minutos
    05/09/2026