dataclasses: clases de datos en Python

Actualizado el: 20/08/2026
Tempo de leitura: 4 minutos
Uso de dataclasses para simplificar classes em Python

Las dataclasses reducen el código repetitivo de clases cuyo propósito principal es almacenar datos. Con el decorador @dataclass, Python puede generar automáticamente métodos como __init__, __repr__ y __eq__ a partir de anotaciones de tipo. Esto mejora la legibilidad y evita errores al mantener constructores manuales con muchos atributos.

Una dataclass sigue siendo una clase normal: puede incluir métodos, propiedades, herencia y validación. Para comprender la base, consulta la guía de programación orientada a objetos en Python.

Crear la primera dataclass

from dataclasses import dataclass

@dataclass
class Producto:
    nombre: str
    precio: float
    stock: int

producto = Producto("Teclado", 49.90, 10)

print(producto)
print(producto.nombre)

El decorador genera un constructor con los tres campos, una representación legible y comparación por valores. Las anotaciones describen la intención, pero Python no valida automáticamente los tipos en tiempo de ejecución.

Valores predeterminados

@dataclass
class Usuario:
    nombre: str
    activo: bool = True
    intentos: int = 0

Los campos sin valor predeterminado deben aparecer antes de los campos con valor predeterminado. Esta regla evita una firma de función inválida.

Evitar valores mutables compartidos

No utilices una lista literal como valor predeterminado. Emplea default_factory:

from dataclasses import dataclass, field

@dataclass
class Pedido:
    cliente: str
    productos: list[str] = field(default_factory=list)

Cada instancia recibe una lista nueva. Este patrón evita que dos pedidos compartan accidentalmente la misma colección.

Personalizar campos con field

field() permite excluir un atributo de la representación, comparación o constructor:

@dataclass
class Cuenta:
    usuario: str
    token: str = field(repr=False)
    id_interno: int = field(init=False, default=0)

repr=False evita mostrar el token en la representación, aunque no sustituye controles de seguridad. init=False impide que el campo sea un parámetro del constructor.

Validar con __post_init__

__post_init__() se ejecuta después del constructor generado:

@dataclass
class Producto:
    nombre: str
    precio: float
    stock: int = 0

    def __post_init__(self) -> None:
        if not self.nombre.strip():
            raise ValueError("El nombre es obligatorio")
        if self.precio < 0:
            raise ValueError("El precio no puede ser negativo")
        if self.stock < 0:
            raise ValueError("El stock no puede ser negativo")

Utiliza este método para invariantes sencillas y conversiones controladas. Si la validación requiere servicios externos o muchas reglas, considera una capa específica.

Campos calculados

@dataclass
class Rectangulo:
    ancho: float
    alto: float
    area: float = field(init=False)

    def __post_init__(self) -> None:
        self.area = self.ancho * self.alto

Si el área debe actualizarse cuando cambian ancho o alto, una propiedad calculada puede ser mejor que almacenar el resultado.

Dataclasses inmutables

@dataclass(frozen=True)
class Punto:
    x: float
    y: float

frozen=True impide la asignación normal después de crear la instancia. Es una protección útil contra cambios accidentales, pero no convierte automáticamente en inmutables los objetos mutables contenidos.

Ordenación de instancias

@dataclass(order=True)
class Tarea:
    prioridad: int
    titulo: str

order=True genera comparaciones siguiendo el orden de los campos. Si solo deseas ordenar por prioridad y no por título, excluye el segundo campo:

@dataclass(order=True)
class Tarea:
    prioridad: int
    titulo: str = field(compare=False)

Campos que son solo argumentos

InitVar permite recibir un valor en el constructor sin guardarlo como campo:

from dataclasses import InitVar, dataclass

@dataclass
class Perfil:
    nombre: str
    clave_temporal: InitVar[str]

    def __post_init__(self, clave_temporal: str) -> None:
        if len(clave_temporal) < 8:
            raise ValueError("Clave temporal demasiado corta")

Evita utilizar este patrón para conservar secretos en memoria sin necesidad.

Convertir a diccionario o tupla

from dataclasses import asdict, astuple

datos = asdict(producto)
valores = astuple(producto)

asdict() convierte dataclasses anidadas de forma recursiva y puede copiar estructuras. Para objetos grandes o serialización controlada, construye explícitamente el esquema esperado.

Reemplazar campos sin modificar el original

from dataclasses import replace

actualizado = replace(producto, precio=44.90)

replace() crea una nueva instancia y vuelve a ejecutar la inicialización correspondiente. Es especialmente útil con dataclasses congeladas.

Herencia

@dataclass
class Persona:
    nombre: str

@dataclass
class Empleado(Persona):
    departamento: str
    salario: float

Los campos heredados participan en el constructor. Debes respetar el orden entre campos obligatorios y predeterminados a través de la jerarquía. Evita árboles complejos cuando la composición sea más clara.

slots para reducir memoria

@dataclass(slots=True)
class Coordenada:
    latitud: float
    longitud: float

slots=True puede reducir memoria y evitar atributos arbitrarios. Revisa la compatibilidad con herencia, serialización y bibliotecas que esperan __dict__.

Dataclass frente a namedtuple y diccionario

Un diccionario es flexible, pero no declara un esquema claro. Una namedtuple es ligera e inmutable, pero ofrece menos posibilidades de validación y valores predeterminados. Una dataclass funciona bien para entidades internas, parámetros y resultados estructurados. Para estudiar anotaciones, revisa type hints en Python.

Dataclass frente a modelos de validación

Las anotaciones no convierten automáticamente strings en números ni validan datos JSON. Cuando los datos provienen de usuarios o APIs, una biblioteca de validación puede ser más adecuada. Las dataclasses son excelentes para representar datos ya confiables dentro de la aplicación.

Añadir métodos y documentación

@dataclass
class Producto:
    # Representa un artículo disponible en inventario.
    nombre: str
    precio: float

    def aplicar_descuento(self, porcentaje: float) -> float:
        return self.precio * (1 - porcentaje / 100)

La guía de docstrings en Python ayuda a documentar responsabilidades y parámetros. El decorador de dataclass también se relaciona con la guía de decoradores en Python.

Enums y estados

Cuando un campo acepta un conjunto cerrado de estados, utiliza un Enum en lugar de strings libres. La guía de Enums en Python muestra cómo evitar valores mágicos.

Fuentes oficiales

La documentación oficial de dataclasses describe todos los parámetros del decorador y de field(). El PEP 557 explica las motivaciones y decisiones de diseño originales.

Errores frecuentes

Los problemas más comunes son usar listas como valores predeterminados, creer que los tipos se validan solos, exponer secretos mediante repr, almacenar campos calculados que quedan obsoletos y activar order=True sin pensar en el orden semántico. También debes evaluar si una clase con mucha lógica sigue siendo principalmente una clase de datos.

Conclusión

Las dataclasses eliminan repetición sin quitar el poder de las clases. Declara campos con tipos, utiliza default_factory para mutables, valida invariantes en __post_init__ y elige frozen, order o slots solo cuando aporten valor. Su mayor beneficio no es ahorrar líneas, sino hacer explícita la estructura de los datos y mantener coherentes la creación, comparación y representación de objetos.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Configuración TOML en un proyecto Python
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    tomllib en Python: lee archivos TOML

    Aprende a leer TOML con tomllib en Python, validar configuraciones, gestionar errores y organizar proyectos con pyproject.toml.

    Ler mais

    Tempo de leitura: 6 minutos
    24/07/2026
    Desarrollador monitoreando registros estructurados en Python
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    Observabilidad en Python con structlog

    Aprende observabilidad en Python con structlog, eventos JSON, contexto, pruebas, control de volumen y recomendaciones para producción.

    Ler mais

    Tempo de leitura: 5 minutos
    24/07/2026
    Configuración segura de aplicaciones Python con Pydantic Settings
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    Pydantic Settings: configuración segura

    Aprende a validar variables de entorno, organizar configuraciones y proteger secretos en proyectos Python con Pydantic Settings.

    Ler mais

    Tempo de leitura: 5 minutos
    23/07/2026
    Desenvolvedor programando em Python com Ruff para lint e formatação
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    Ruff: lint y formato de código Python

    Aprende Ruff en Python para lint, formato, correcciones automáticas, pyproject.toml, VS Code y CI con una configuración práctica.

    Ler mais

    Tempo de leitura: 10 minutos
    22/07/2026
    Dicas para melhorar performance de scripts Python lentos
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    ¿Por qué Python es lento? Causas y optimización

    Descubre por qué Python puede ser lento y mejora su rendimiento con cProfile, algoritmos, sets, generadores, NumPy, caché y concurrencia.

    Ler mais

    Tempo de leitura: 5 minutos
    12/07/2026
    Leitura segura de senhas no terminal usando Python
    Buenas Prácticas
    Foto de perfil de Leandro Hirt da Academify

    getpass: lee contraseñas en terminal con Python

    Lee contraseñas de forma segura con getpass, valida entradas, evita logs y texto plano y almacena credenciales con hashing adecuado.

    Ler mais

    Tempo de leitura: 5 minutos
    11/07/2026