Os "dunder methods" (de "double underscore" - dois sublinhados) são métodos especiais em Python que você não chama diretamente, mas que são invocados automaticamente pelo Python em certas situações. Eles permitem que suas classes interajam com funcionalidades e sintaxes built-in do Python de uma forma muito poderosa e intuitiva.

Pense neles como "ganchos" que você pode implementar em suas classes para que elas se comportem como os tipos de dados nativos do Python (como listas, strings, números, etc.) ou para definir um comportamento padrão para operações comuns.

Para que servem EXATAMENTE?

Eles servem para:

  1. Imitar Comportamentos de Tipos Built-in: Quer que seu objeto possa ser somado com +? Ou comparado com ==? Ou que possa ser iterado com um for? Os dunder methods são a forma de fazer isso.
  2. Personalizar o Comportamento Padrão do Python: Quando você usa print() em um objeto, o Python chama o __str__ dele. Se você não definir __str__, ele terá uma saída padrão genérica. Com o dunder method, você personaliza essa saída.
  3. Facilitar o Uso da Sua Classe: Ao tornar seus objetos compatíveis com operadores e funções built-in, você torna seu código mais legível, pythonico e fácil de usar para quem for trabalhar com suas classes.

Vamos esmiuçar os exemplos que você viu, focando no "para que serve" de cada um:

2.2.5.1 __init__(self, ...): O "Construtor"

2.2.5.2 __str__(self): A Representação "Amigável" para Usuários

2.2.5.3 __repr__(self): A Representação "Oficial" para Desenvolvedores

2.2.5.4 __eq__(self, other): Comparação de Igualdade (==)