Saltar al contenido principal
Intermedio45 minutos
Prerequisitos: Clases y Objetos · Type Hints
Módulo 04: Programación Orientada a ObjetosLección 2 de 2
100% completado

Dataclasses en Python

🗺️ Mapa de la Lección

45 minutos🟡 Intermedio

🎯 Qué aprenderás

  • Entender qué son las dataclasses y cuándo usarlas
  • Crear dataclasses con @dataclass
  • Usar campos con valores por defecto
  • Aplicar frozen para inmutabilidad
  • Comparar objetos automáticamente

🌍 Para qué te sirve

  • Clases que principalmente almacenan datos (estructuras de datos)
  • Configuraciones: settings, opciones de aplicación
  • Resultados de funciones: devolver múltiples valores estructurados
  • DTOs (Data Transfer Objects): transferir datos entre capas
  • Modelos simples: cuando no necesitas lógica compleja
  • Comparación automática: cuando necesitas __eq__ automático

🎯 ¿Por qué aprender dataclasses?

Imagina que necesitas una clase solo para guardar datos (como un usuario, una configuración, o un producto). Con clases normales escribirías mucho código repetitivo para __init__, __repr__, __eq__, etc.

Las dataclasses te permiten:

  • Escribir menos código: Python genera métodos automáticamente
  • Código más legible: sintaxis más clara y concisa
  • Comparación automática: __eq__ generado automáticamente
  • Representación automática: __repr__ útil por defecto
  • Menos errores: menos código manual = menos bugs

🌍 Casos reales donde se usa

Las dataclasses son perfectas para clases que principalmente almacenan datos:

  • Configuraciones: Settings, opciones de aplicación
  • Resultados de funciones: Devolver múltiples valores estructurados
  • DTOs (Data Transfer Objects): Transferir datos entre capas
  • Modelos simples: Cuando no necesitas lógica compleja
  • Estructuras de datos: Clases que principalmente almacenan información

Ejemplo real: Un sistema de configuración usa dataclasses para representar opciones: @dataclass class Config: host: str, port: int, debug: bool. Python genera automáticamente todos los métodos necesarios.

💡 Concepto base

Las dataclasses son una forma simplificada de crear clases que principalmente almacenan datos. Con un simple decorador @dataclass, Python genera automáticamente __init__, __repr__, __eq__ y más.

Lo genial de Python: Puedes crear clases de datos con mucho menos código que las clases tradicionales.

from dataclasses import dataclass

# Con dataclass (simple y claro)
@dataclass
class Persona:
nombre: str
edad: int
email: str

# Crear instancia
persona = Persona("Ana", 25, "ana@email.com")
print(persona) # Representación automática
Resultado esperado:
Persona(nombre='Ana', edad=25, email='ana@email.com')
🌮 Analogía culinaria

Las dataclasses son como una plantilla predefinida para crear chilaquiles al pastor. En lugar de escribir cada vez todos los pasos (cortar tortillas, freír, agregar salsa, queso, pastor), defines una vez la estructura básica y Python automáticamente te da todos los métodos necesarios. Es como tener un molde que ya sabe cómo crear el plato completo, solo necesitas especificar los ingredientes y el molde hace el resto del trabajo. Mucho más rápido y menos propenso a errores.

Para principiantes

Antes de continuar: Asegúrate de entender Clases y Objetos y Type Hints.

¿Cuándo usar dataclasses?

  • Clases que principalmente almacenan datos
  • Cuando necesitas comparación automática entre objetos
  • Configuraciones y estructuras simples

¿Cuándo NO usar dataclasses?

  • Clases con mucha lógica de negocio (usa clases normales)
  • Cuando necesitas control total sobre __init__ o métodos especiales

Antes de continuar: Asegúrate de entender Clases y Type Hints.

Conceptos Básicos

Creación Básica

Con el decorador @dataclass, Python genera automáticamente los métodos necesarios:

from dataclasses import dataclass

@dataclass
class Persona:
nombre: str
edad: int
email: str

¿Qué hace @dataclass automáticamente?

  • Genera __init__() con los parámetros
  • Genera __repr__() para mostrar el objeto
  • Genera __eq__() para comparar objetos
  • Y más métodos útiles

Uso:

# Crear objeto - igual que una clase normal
persona1 = Persona("Ana", 28, "ana@email.com")
persona2 = Persona("Ana", 28, "ana@email.com")

print(persona1) # Persona(nombre='Ana', edad=28, email='ana@email.com')
print(persona1 == persona2) # True (comparación automática)

Comparación con clase normal: Esto es equivalente a ~20 líneas de código en una clase normal.

Con Valores por Defecto

Puedes dar valores por defecto a los atributos:

@dataclass
class Configuracion:
host: str = "localhost" # Valor por defecto
puerto: int = 8080 # Valor por defecto
debug: bool = False # Valor por defecto

Uso:

# Usar todos los valores por defecto
config1 = Configuracion() # host="localhost", puerto=8080, debug=False

# Sobrescribir algunos
config2 = Configuracion(host="192.168.1.1", puerto=3000)
# host="192.168.1.1", puerto=3000, debug=False (usa el default)

# Especificar todos
config3 = Configuracion(host="prod.server.com", puerto=443, debug=True)

Importante: Los atributos con valores por defecto deben ir después de los que no tienen. Python requiere esto.

Características Avanzadas

Inmutabilidad

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

Comparación Personalizada

@dataclass(order=True)
class Producto:
nombre: str
precio: float
stock: int

Ejemplos de Uso

Validación de Datos

@dataclass
class ErrorValidacion:
fila: int
campo: str
valor: str
mensaje: str

# Uso
error = ErrorValidacion(
fila=1,
campo="email",
valor="invalido",
mensaje="Formato de email incorrecto"
)

Configuración

@dataclass
class ConfiguracionDB:
host: str
puerto: int
usuario: str
password: str
base_datos: str

# Uso
config = ConfiguracionDB(
host="localhost",
puerto=5432,
usuario="admin",
password="secret",
base_datos="mi_db"
)

Métodos Especiales

Post Init

@dataclass
class Rectangulo:
ancho: float
alto: float
area: float = None

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

Métodos Personalizados

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

def tiene_stock(self) -> bool:
return self.stock > 0

def valor_total(self) -> float:
return self.precio * self.stock

Buenas Prácticas

  1. Usa Type Hints
@dataclass
class Usuario:
id: int
nombre: str
activo: bool
  1. Documenta tus Clases
@dataclass
class Transaccion:
"""Representa una transacción financiera."""
id: int
monto: float
fecha: str
  1. Considera la Inmutabilidad
@dataclass(frozen=True)
class Constantes:
PI: float = 3.14159
GRAVEDAD: float = 9.81

Ejemplo Práctico

from dataclasses import dataclass
from typing import List, Optional
from datetime import datetime

@dataclass
class Orden:
id: int
cliente: str
productos: List[str]
total: float
fecha: datetime
estado: str = "pendiente"
notas: Optional[str] = None

def __post_init__(self):
if self.total < 0:
raise ValueError("El total no puede ser negativo")

def esta_completada(self) -> bool:
return self.estado == "completada"

def agregar_producto(self, producto: str, precio: float):
self.productos.append(producto)
self.total += precio

Consejos

  1. Usa dataclasses para estructuras de datos simples
  2. Aprovecha los type hints para mejor documentación
  3. Considera usar frozen=True para datos inmutables
  4. Usa __post_init__ para validaciones y cálculos

Recursos Adicionales

Documentación Oficial

Bibliografía Recomendada

  • Fluent Python (Luciano Ramalho) - Capítulo 5: Data Class Builders
  • Effective Python (Brett Slatkin) - Item 37: Use Comprehensions Instead of map and filter
  • Python Tricks (Dan Bader) - Capítulo sobre dataclasses
  • Python Cookbook, 3rd Ed (Beazley & Jones) - Recetas sobre dataclasses

Conceptos Relacionados


Siguiente paso

Ahora que conoces las dataclasses, aprende a manejar errores de manera profesional. Continúa con: Manejo de Excepciones