El decorador @dataclass es una de las herramientas introducidas en Python 3.7 para reducir el código boilerplate al crear clases simples de almacenamiento de datos. Gracias a las anotaciones de tipos, Python genera automáticamente los métodos __init__, __repr__, __eq__ y otros.
Historia del tema:
Antes de la llegada de dataclass, los desarrolladores escribían clases de plantilla manualmente, implementando constructores, métodos de comparación, repr, y después a menudo cambiaban a tuplas nombradas o bibliotecas como attrs. La introducción de @dataclass estandarizó y simplificó este proceso.
Problema:
El código boilerplate, la duplicación de código de constructores y métodos de comparación a menudo conducían a errores y complicaban el mantenimiento de aplicaciones grandes.
Solución:
El uso de anotaciones de tipos y el decorador especial @dataclass permite generar automáticamente todos los métodos necesarios en la clase.
Ejemplo de código:
from dataclasses import dataclass @dataclass class Point: x: int y: int p1 = Point(10, 20) p2 = Point(10, 20) print(p1 == p2) # True, __eq__ generado automáticamente print(p1) # Point(x=10, y=20), __repr__ generado automáticamente
Características clave:
¿Modifica @dataclass el comportamiento de la herencia (particularidades en la herencia)?
Sí. En la herencia de clases dataclass, hay que prestar atención especial: los campos de la clase base vienen antes que los campos de la clase hija, y también pueden surgir errores en conflictos de constructores/orden de argumentos. Si la clase base y la hija tienen campos con los mismos nombres, el último eclipsará al anterior.
¿Se pueden usar valores mutables por defecto para los campos en dataclass?
No, no se pueden usar directamente esos objetos (por ejemplo, listas) como predeterminados; se debe utilizar field(default_factory=list). De lo contrario, todas las instancias de la clase compartirán la misma colección.
Ejemplo:
from dataclasses import dataclass, field @dataclass class User: values: list = field(default_factory=list)
¿Es @dataclass rápido para cualquier escenario? ¿Es adecuado para almacenar de manera óptima grandes volúmenes de datos?
No. dataclass no es la opción más eficiente para optimización de memoria. Para almacenar millones de objetos, es mejor usar __slots__, namedtuple o estructuras especiales; dataclass añade campos de servicio y no ahorra memoria como lo hacen los slots. Se puede combinar pasando el parámetro slots=True (Python 3.10+), o usar slots manualmente.
@dataclass class Cart: items: list = [] # ¡error! c1 = Cart() c2 = Cart() c1.items.append("a") print(c2.items) # ['a'] — todos los Cart comparten una lista
Ventajas:
Desventajas:
from dataclasses import dataclass, field @dataclass class Cart: items: list = field(default_factory=list) c1 = Cart() c2 = Cart() c1.items.append("a") print(c2.items) # []
Ventajas:
Desventajas:
field(default_factory=...) (lo que requiere un estudio aparte).