asdict() convierte una dataclass en un diccionario y baja recursivamente hasta el fondo, copiando por el camino. Normalmente es lo que quieres, y de vez en cuando es exactamente lo que no.
Cuatro formas de guardar datos estructurados en Python. La pregunta que decide no es de estilo: es si un error de tipeo debería fallar en voz alta.
Cada operador y cada función incorporada de Python le está haciendo una pregunta a tu objeto. Contéstala y tu clase se comporta como un tipo nativo.
La herencia le da a una subclase todo, incluso lo que no debería tener. El problema del pingüino, y qué hacer en su lugar.
La pregunta siempre es solo qué necesita el método: esta instancia, la clase, o ninguna de las dos. Equivocarse rompe las subclases sin avisar.
Python no necesita getters ni setters, porque @property te deja agregar validación después sin cambiar ni una sola llamada.
Una clase sin __repr__ te hace perder tiempo desde el momento en que existe. repr es para ti, str es para quien lee, y solo uno de los dos tiene un respaldo razonable.
self es el nombre de un parámetro, no una palabra reservada. __init__ no crea el objeto. Y un atributo de clase es compartido hasta el momento en que asignas a través de una instancia.
La mayoría de las clases en Python debieron ser funciones. La prueba no es «¿esto es un sustantivo?», sino si existe un estado inválido que la clase pueda impedir.
El bucle que estás por escribir probablemente ya está en la biblioteca estándar. islice, chain, pairwise y groupby cubren casi todos, y groupby tiene una regla que no te puedes saltar.