O problema Link para o cabeçalho

Para um objeto responder a <, <=, >, >=, == e !=, o Python espera que você implemente __lt__, __le__, __gt__, __ge__, __eq__ e __ne__. São seis métodos quase idênticos, tediosos de escrever e fáceis de deixar inconsistentes (um diz que a < b e outro discorda).

A dica Link para o cabeçalho

Duas peças cobrem tudo:

  • O dataclass já gera o __eq__, comparando todos os campos do objeto.
  • O decorador functools.total_ordering deriva __le__, __gt__ e __ge__ a partir do __eq__ e de um método de ordem.

Ou seja, você escreve só o __lt__ e ganha o conjunto completo.

Código Link para o cabeçalho

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from dataclasses import dataclass
from decimal import Decimal
from functools import total_ordering


@dataclass(frozen=True)
@total_ordering
class Money:
    amount: Decimal
    currency: str = "BRL"

    def __lt__(self, other):
        if not isinstance(other, Money):
            return NotImplemented
        return self.amount < other.amount

O isinstance evita comparar Money com tipos alheios: retornar NotImplemented deixa o outro lado tentar. Com isso, ordenar uma lista de preços com sorted() passa a funcionar de graça.

De onde veio o exemplo Link para o cabeçalho

A classe Money é a mesma do artigo “O Objeto Dinheiro”, vinda do capital_gains/money.py, uma refatoração de teste técnico onde explorei técnicas mais avançadas de Python.

Então é isso, pessoal!

Até a próxima!

{}’s