O asdict() converte uma dataclass em dict e desce recursivamente até o fim, copiando no caminho. Quase sempre é o que você quer, e de vez em quando é bem o contrário.
O laço que você está prestes a escrever provavelmente já está na biblioteca padrão. islice, chain, pairwise e groupby cobrem a maioria, e o groupby tem uma regra que você não pode pular.
Um generator é um iterador que você escreve como uma função comum. Ele pausa no yield, volta de onde parou, e nunca monta a lista que você ia montar.
Um laço for são três passos que você mesmo poderia escrever. Depois de ver os três, o bug do vazio na segunda vez deixa de ser surpresa e vira óbvio.
Dois builtins que substituem o contador que você escreve na mão e a indexação que você erra. Um deles também joga dados fora sem avisar.
Todo operador, toda função embutida, toda sintaxe do Python é uma pergunta feita ao seu objeto. O modelo de dados é a lista de perguntas.
__slots__ elimina o dicionário por instância. Economiza memória de verdade em escala, pega erros de digitação de graça, e é o padrão errado.
Duck typing falha no ponto da chamada, muito depois do erro. ABCs e Protocols resolvem isso, em direções opostas.
Quatro jeitos de guardar dados estruturados em Python. A pergunta que decide não é estilo — é se um erro de digitação deve falhar alto.
Todo operador e toda função embutida do Python está fazendo uma pergunta ao seu objeto. Responda e sua classe passa a se comportar como um tipo nativo.