
Passo 1 de 9
Escolher o que torna dois objetos iguais
Defina igualdade de valor para uma versão numérica, separando seus componentes essenciais de informações apenas descritivas.
Trilha de aprendizado · Nível 11 · Tutorial 2
Ao concluir, você poderá estabelecer comparações coerentes para objetos de domínio e permitir sua ordenação quando essa operação tiver significado.
Escolher o que torna dois objetos iguais
Defina igualdade de valor para uma versão numérica, separando seus componentes essenciais de informações apenas descritivas. 2 min
Implementar o contrato com __eq__
Implemente a igualdade de valor de Versao com os componentes significativos, tipos aceitos de forma explícita e o sinal correto para comparações fora do contrato. 3 min
Entender NotImplemented e a resposta do outro operando
Veja como Python negocia uma comparação de igualdade quando um dos objetos não reconhece o outro. 3 min
Conhecer o protocolo das comparações de ordem
Entenda quais métodos especiais atendem aos operadores de ordem e por que tipos incompatíveis podem resultar em TypeError. 2 min
Construir uma ordem com critérios sucessivos
Implemente uma ordem numérica coerente para versões, usando os componentes significativos na prioridade correta. 3 min
Completar as relações com total_ordering
Use um decorador da biblioteca padrão para derivar as relações de ordem que faltam, sem abrir mão de um contrato coerente. 2 min
Escolher entre ordem do objeto e chave externa
Use a ordem própria de Versao quando ela expressar o valor do domínio e use key quando o critério pertencer apenas à tarefa atual. 2 min
Testar as propriedades do contrato
Use propriedades e contraexemplos pequenos para revelar divergências entre igualdade, ordem e tipos incompatíveis. 3 min
Aplicar e revisar as comparações de uma classe
Conclua uma implementação de referência, execute verificações locais e explique como igualdade, ordem e tipos incompatíveis se comportam. 4 min

Passo 1 de 9
Defina igualdade de valor para uma versão numérica, separando seus componentes essenciais de informações apenas descritivas.
Duas variáveis podem apontar para o mesmo objeto; isso é identidade. Já a igualdade de valor responde outra pergunta: esses dois objetos representam o mesmo valor no domínio?
Essa resposta não é automática. Você escolhe quais atributos participam do contrato de igualdade da classe.
Observe que referências diferentes podem representar o mesmo valor de versão.

Identidade trata de referências; igualdade de valor trata dos dados que o domínio considera significativos.
No nosso caso, uma Versao tem três componentes numéricos: principal, secundaria e correcao. Ela também possui uma nota, como “versão estável” ou “implantação do cliente A”.
A nota ajuda a descrever ou apresentar a instância, mas não muda a versão numérica. Portanto, duas instâncias representam o mesmo valor quando os três componentes numéricos coincidem. Inicialmente, esse contrato vale somente entre instâncias do tipo concreto Versao.
Exemplo
Considere estas instâncias distintas:
v1 = Versao(2, 4, 1, nota="versão estável")
v2 = Versao(2, 4, 1, nota="implantação cliente A")
v3 = Versao(2, 4, 2, nota="correção liberada")v1 e v2 devem ser iguais em valor: (2, 4, 1) é igual a (2, 4, 1).v1 e v3 devem ser diferentes: o componente correcao mudou de 1 para 2.v1 e v2 continuam sendo instâncias separadas, mesmo representando o mesmo valor.Segundo o contrato definido para Versao, qual par deve representar o mesmo valor?

Passo 2 de 9
Implemente a igualdade de valor de Versao com os componentes significativos, tipos aceitos de forma explícita e o sinal correto para comparações fora do contrato.
Quando Python avalia esquerda == direita, ele usa __eq__ para a comparação de igualdade. Para duas instâncias de Versao, o resultado suportado deve ser um booleano: True se principal, secundaria e correcao forem iguais; False se algum desses componentes diferir.
A nota continua fora da comparação: ela descreve a versão, mas não define seu valor no domínio.
A igualdade olha para a tripla numérica, não para a nota.

Instâncias diferentes podem ser iguais em valor quando os três componentes numéricos coincidem.
Compare somente os atributos que o contrato definiu como significativos.
class Versao:
def __init__(self, principal, secundaria, correcao, nota):
self.principal = principal
self.secundaria = secundaria
self.correcao = correcao
self.nota = nota
def __eq__(self, outro):
if type(outro) is not type(self):
return NotImplemented
return (
self.principal == outro.principal
and self.secundaria == outro.secundaria
and self.correcao == outro.correcao
)Aqui, type(outro) is not type(self) restringe o contrato ao mesmo tipo concreto antes de ler atributos de outro. Uma alternativa seria isinstance(outro, Versao), que também aceitaria subclasses. Não é a política escolhida neste contrato: uma subclasse pode acrescentar critérios de valor próprios.
Se o tipo não é aceito, retorne NotImplemented. Isso não quer dizer que as versões são diferentes; sinaliza que este método não realiza aquela comparação. No próximo passo, você verá como Python trata esse sinal ao avaliar o operador ==.
Exemplo
v1 = Versao(2, 4, 1, "estável")
v2 = Versao(2, 4, 1, "revisada")
v3 = Versao(2, 4, 2, "correção nova")
print(v1 == v2) # True: a nota não participa
print(v1 == v3) # False: correcao é diferente
print(v1.__eq__("2.4.1")) # NotImplemented: chamada direta
print(v1 != v2) # False
print(v1 != v3) # TrueVocê normalmente não precisa escrever __ne__. Quando __eq__ devolve True ou False, o comportamento herdado de != inverte esse resultado. Se __eq__ devolve NotImplemented, não há inversão direta por esse método.
Complete o retorno para quando outro não tiver o mesmo tipo concreto:
def __eq__(self, outro):
if type(outro) is not type(self):
return _____Considere a = Versao(1, 0, 3, "interna") e b = Versao(1, 0, 3, "lançamento"). Qual é o resultado de a != b?

Passo 3 de 9
Veja como Python negocia uma comparação de igualdade quando um dos objetos não reconhece o outro.
Em __eq__, False e NotImplemented comunicam coisas diferentes.
False quando a comparação é aceita, mas os valores são diferentes.NotImplemented quando esse método não sabe comparar o outro operando.Por exemplo, duas Versao podem ser comparadas entre si e resultar em False. Já comparar uma Versao com um objeto de outro tipo está fora do contrato definido pela classe.
A imagem contrasta uma comparação suportada com uma comparação que precisa ser delegada ao protocolo de Python.

False encerra uma comparação suportada; NotImplemented pede que Python procure outra implementação.
Atenção
NotImplemented é um valor especial para retornar, não para lançar com raise. Também não escreva bool(NotImplemented) nem o use em um if: esse uso é inadequado e gera aviso de depreciação. Deixe o operador == conduzir o protocolo.
Execute este exemplo no seu interpretador Python.
class Versao:
def __eq__(self, outro):
if type(outro) is not Versao:
return NotImplemented
return True
versao = Versao()
print(versao.__eq__(42)) # NotImplemented
print(versao == 42) # False
print(versao != 42) # TrueA chamada direta versao.__eq__(42) mostra exatamente o retorno daquele método: NotImplemented.
Já versao == 42 ativa o protocolo de comparação. Depois que Versao.__eq__ recusa o inteiro, Python pode consultar a implementação do outro operando. Se ninguém aceitar a igualdade, == recorre à identidade: objetos distintos resultam em False. Por consequência, != resulta em True.
Em uma expressão esquerdo == direito, Python tenta resolver a igualdade pelos métodos dos tipos envolvidos. Se a primeira implementação retorna NotImplemented, a outra pode responder.
Há uma regra importante: se o tipo do operando direito for uma subclasse estrita do tipo do esquerdo, Python dá prioridade à implementação do tipo mais específico, a do lado direito.
Cada método imprime quando é consultado.
class A:
def __eq__(self, outro):
print("A.__eq__")
return NotImplemented
class B:
def __eq__(self, outro):
print("B.__eq__")
return True
print(A() == B())
# Saída:
# A.__eq__
# B.__eq__
# True
class Base:
def __eq__(self, outro):
print("Base.__eq__")
return NotImplemented
class Especial(Base):
def __eq__(self, outro):
print("Especial.__eq__")
return True
print(Base() == Especial())
# Saída:
# Especial.__eq__
# TruePara A() == B() no primeiro exemplo, ordene os eventos.
Se esquerdo.__eq__(direito) e a tentativa aplicável no outro operando retornam NotImplemented, então esquerdo == direito gera TypeError.
Resumo
Use este roteiro ao ler ou implementar uma igualdade entre tipos diferentes.
False afirma que uma comparação suportada foi feita e os valores diferem.NotImplemented informa que aquele método não sabe comparar o par recebido.== faz mais do que uma chamada direta: ele pode consultar o outro operando.TypeError nesse caso.
Passo 4 de 9
Entenda quais métodos especiais atendem aos operadores de ordem e por que tipos incompatíveis podem resultar em TypeError.
Em uma expressão de ordem, Python consulta métodos especiais do tipo dos operandos. A correspondência direta é:
a < b → a.__lt__(b)a <= b → a.__le__(b)a > b → a.__gt__(b)a >= b → a.__ge__(b)Ao contrário de ==, definir __eq__ não dá significado automático a <, <=, > ou >=. Uma classe pode ter igualdade de valor e, ainda assim, não ter uma ordem definida.
Os pares refletidos usam o operador de sentido oposto com os operandos trocados.

Se a tentativa de a < b não for aceita, Python pode consultar a operação correspondente b > a.
Uma implementação que não sabe ordenar o par deve retornar NotImplemented. Então Python tenta a operação refletida correspondente no outro operando — respeitando também a prioridade de subclasses vista anteriormente.
Para esquerda < direita, a tentativa refletida é direita.__gt__(esquerda). Para esquerda <= direita, é direita.__ge__(esquerda).
Se nenhuma implementação aceitar a operação, a expressão de ordem levanta TypeError. Isso difere da igualdade: quando ambos os lados não suportam ==, Python pode recorrer à identidade; em ordem, não há esse recurso final.
Execute localmente para observar a falha de ordem.
class Versao:
def __init__(self, principal, secundaria, correcao):
self.principal = principal
self.secundaria = secundaria
self.correcao = correcao
def __eq__(self, outro):
if type(outro) is not Versao:
return NotImplemented
return (
self.principal,
self.secundaria,
self.correcao,
) == (
outro.principal,
outro.secundaria,
outro.correcao,
)
v1 = Versao(1, 2, 0)
v2 = Versao(1, 2, 0)
print(v1 == v2) # True
print(v1 < v2) # TypeError: '<' not supported ...
Relacione cada expressão à chamada que Python pode tentar caso a implementação direta retorne NotImplemented.
Toque em um item e depois no par correspondente.
Uma instância de Versao retorna NotImplemented em __lt__ ao receber um str, e o str também não suporta a comparação refletida. Qual é o resultado de versao < "2.0"?

Passo 5 de 9
Implemente uma ordem numérica coerente para versões, usando os componentes significativos na prioridade correta.
Uma versão é comparada em etapas: primeiro principal, depois secundaria e, somente se houver empate, correcao. O primeiro componente diferente decide qual versão vem antes.
Assim, 2.0.9 < 2.1.0 porque 0 < 1 na parte secundária. A correção nem precisa ser consultada.
A ordem de consulta é fixa: principal → secundária → correção.

Só avance para o próximo componente quando o anterior for igual.
Tuplas são comparadas lexicograficamente em Python. Portanto, a tupla dos componentes traduz diretamente o contrato de ordem da versão.
Use a mesma política de tipos adotada em __eq__: somente instâncias do mesmo tipo concreto participam da comparação.
class Versao:
def __init__(self, principal, secundaria, correcao, nota=""):
self.principal = principal
self.secundaria = secundaria
self.correcao = correcao
self.nota = nota
def __eq__(self, outro):
if type(outro) is not type(self):
return NotImplemented
return (
self.principal,
self.secundaria,
self.correcao,
) == (
outro.principal,
outro.secundaria,
outro.correcao,
)
def __lt__(self, outro):
if type(outro) is not type(self):
return NotImplemented
return (
self.principal,
self.secundaria,
self.correcao,
) < (
outro.principal,
outro.secundaria,
outro.correcao,
)Exemplo
Versao(2, 10, 0) deve vir depois de Versao(2, 9, 0), pois 10 > 9.
Já os textos formatados '2.10.0' e '2.9.0' teriam ordem lexicográfica de caracteres, levando ao resultado incorreto: '2.10.0' < '2.9.0'. Compare os números, não a representação textual.
Dica
Os três componentes numéricos participam tanto de __eq__ quanto de __lt__. A nota continua fora das duas comparações: ela descreve a versão, mas não define seu valor nem sua posição na ordem.
Organize estas versões da menor para a maior, usando a ordem numérica dos componentes.
Na comparação Versao(3, 7, 99) < Versao(3, 12, 0), qual componente decide o resultado?

Passo 6 de 9
Use um decorador da biblioteca padrão para derivar as relações de ordem que faltam, sem abrir mão de um contrato coerente.
Quando uma classe já define uma igualdade coerente em __eq__ e uma relação de ordem, como __lt__, o decorador functools.total_ordering pode fornecer os demais métodos de ordem.
No caso de Versao, __eq__ define quando dois valores são iguais e __lt__ define qual vem antes. Essa é uma base suficiente para usar o decorador.
Parta de __eq__ e __lt__; o decorador acrescenta as relações ausentes.

Você implementa a igualdade e uma relação de ordem; total_ordering deriva as outras três relações de ordem.
Coloque o decorador imediatamente acima da classe.
from functools import total_ordering
@total_ordering
class Versao:
def __init__(self, principal, secundaria, correcao, nota):
self.principal = principal
self.secundaria = secundaria
self.correcao = correcao
self.nota = nota
def __eq__(self, outro):
if type(outro) is not Versao:
return NotImplemented
return (
self.principal,
self.secundaria,
self.correcao,
) == (
outro.principal,
outro.secundaria,
outro.correcao,
)
def __lt__(self, outro):
if type(outro) is not Versao:
return NotImplemented
return (
self.principal,
self.secundaria,
self.correcao,
) < (
outro.principal,
outro.secundaria,
outro.correcao,
)Dica
total_ordering não cria __eq__, não substitui métodos que você já escreveu e não verifica se igualdade e ordem usam critérios compatíveis. Ele apenas deriva relações ausentes a partir do contrato que você forneceu.
Execute após a definição da classe.
a = Versao(1, 4, 0, "estável")
b = Versao(1, 4, 0, "mesmo valor, outra nota")
c = Versao(1, 4, 1, "correção")
print(a <= b) # True
print(c > a) # True
print(a >= c) # False
print(a <= "1.4.0") # TypeErrora <= b é verdadeiro porque os valores são iguais. c > a é verdadeiro porque (1, 4, 1) vem depois de (1, 4, 0). Já a <= "1.4.0" termina em TypeError: os métodos recebem um tipo fora do contrato e retornam NotImplemented; nenhuma comparação de ordem suportada resta para a expressão.
Para usar @total_ordering, uma classe deve implementar __eq__ e pelo menos um método de ordem. No exemplo, esse método é ____.
Qual afirmação descreve corretamente total_ordering?

Passo 7 de 9
Use a ordem própria de Versao quando ela expressar o valor do domínio e use key quando o critério pertencer apenas à tarefa atual.
sorted(versoes) usa a ordem própria dos objetos: no caso de Versao, a comparação numérica por (principal, secundaria, correcao), definida por __lt__.
Já sorted(versoes, key=...) transforma cada objeto em uma chave para aquela ordenação. Isso é apropriado quando o critério é contextual — por exemplo, apresentar versões pela nota — e não deve mudar o significado de igualdade nem da ordem numérica de Versao.
A mesma lista pode ter uma ordem de domínio e uma ordem de apresentação.

A ordenação direta segue o valor da versão; a chave externa segue a necessidade da tela.
Considere que Versao já implementa __eq__ e __lt__ com total_ordering.
versoes = [
Versao(2, 0, 0, "estável"),
Versao(1, 10, 0, "correção"),
Versao(1, 2, 0, "alfa"),
]
# Critério que pertence ao objeto: componentes numéricos.
por_versao = sorted(versoes)
# Critério da apresentação atual: texto da nota.
por_nota = sorted(versoes, key=lambda versao: versao.nota)
print([str(v) for v in por_versao])
# ['1.2.0', '1.10.0', '2.0.0']
print([v.nota for v in por_nota])
# ['alfa', 'correção', 'estável']Exemplo
Duas instâncias podem ter notas diferentes e, ainda assim, ser iguais se seus componentes numéricos forem iguais:
Versao(1, 0, 0, "inicial") == Versao(1, 0, 0, "lançamento") → True
Ordenar por key=lambda v: v.nota não altera esse resultado. A chave é usada somente para produzir a ordem pedida naquela chamada de sorted.
Uma chave pode empatar mesmo para objetos diferentes. Por exemplo, duas versões distintas podem ter a nota "beta"; elas continuam diferentes pela igualdade numérica, mas recebem a mesma chave textual.
Além disso, uma classe que não possui uma ordem de domínio ainda pode ser ordenada por key, desde que os valores retornados pela chave sejam comparáveis.
A classe abaixo não define comparações. Ainda assim, a lista pode ser ordenada pela prioridade numérica extraída por key.
class Tarefa:
def __init__(self, titulo, prioridade):
self.titulo = titulo
self.prioridade = prioridade
def __repr__(self):
return f"Tarefa({self.titulo!r}, {self.prioridade})"
pendentes = [
Tarefa("documentar", 2),
Tarefa("corrigir", 1),
]
print(sorted(pendentes, key=lambda tarefa: tarefa.prioridade))
# [Tarefa('corrigir', 1), Tarefa('documentar', 2)]Uma tela de lançamentos deve mostrar objetos Versao em ordem alfabética de nota, mas a classe já possui ordem numérica coerente. Qual é a melhor escolha?

Passo 8 de 9
Use propriedades e contraexemplos pequenos para revelar divergências entre igualdade, ordem e tipos incompatíveis.
Além de testar exemplos pontuais, teste propriedades do contrato.
Para igualdade: uma versão é igual a si mesma (reflexividade); se a == b, então b == a (simetria); e, se a == b e b == c, então a == c (transitividade).
Para a ordem estrita <: nunca vale a < a (irreflexividade); se a < b, não pode valer b < a (assimetria); e, se a < b e b < c, então a < c (transitividade). Em uma ordem total, objetos iguais não precedem um ao outro, e dois valores diferentes comparáveis precisam ter uma direção: a < b ou b < a.
Use esta sequência como mapa para escolher exemplos de teste.

Compare instâncias de mesmo valor, pares com desempate e trios crescentes: cada grupo revela uma propriedade diferente.
Dica
Use notas diferentes para confirmar que a nota não participa da igualdade. Para a ordem, crie pares em que o desempate ocorre primeiro em principal, depois em secundaria e, por fim, em correcao.
Este trecho pressupõe que Versao já está definida em versao.py com __eq__, __lt__ e total_ordering.
import pytest
from versao import Versao
def test_igualdade_eh_reflexiva_simetrica_e_transitiva():
a = Versao(1, 2, 3, "estável")
b = Versao(1, 2, 3, "publicada")
c = Versao(1, 2, 3, "revisada")
assert a == a
assert a == b and b == a
assert a == b and b == c and a == c
def test_iguais_nao_precedem_um_ao_outro():
a = Versao(2, 0, 1, "nota A")
b = Versao(2, 0, 1, "nota B")
assert a == b
assert not (a < b)
assert not (b < a)
@pytest.mark.parametrize(
("menor", "maior"),
[
(Versao(1, 9, 9, ""), Versao(2, 0, 0, "")),
(Versao(2, 1, 9, ""), Versao(2, 2, 0, "")),
(Versao(2, 2, 1, ""), Versao(2, 2, 2, "")),
],
)
def test_cada_componente_pode_decidir_o_desempate(menor, maior):
assert menor < maior
assert not (maior < menor)
def test_menor_que_eh_irreflexivo_e_transitivo():
a = Versao(1, 0, 0, "")
b = Versao(1, 1, 0, "")
c = Versao(2, 0, 0, "")
assert not (a < a)
assert a < b and b < c and a < cUm método da classe deve devolver NotImplemented ao receber um tipo fora do contrato. Já o operador executa o protocolo completo: para igualdade, o resultado final entre objetos sem suporte costuma ser False; para ordem, a ausência de suporte dos dois lados produz TypeError.
Faça as expressões incompatíveis nas duas posições. Isso evita testar apenas o caminho em que Versao ficou à esquerda.
Adicione estes testes à sua suíte.
import pytest
from versao import Versao
def test_metodos_recusam_tipo_fora_do_contrato():
versao = Versao(1, 0, 0, "inicial")
assert versao.__eq__("1.0.0") is NotImplemented
assert versao.__lt__("1.0.0") is NotImplemented
def test_igualdade_incompativel_termina_em_false_nos_dois_sentidos():
versao = Versao(1, 0, 0, "inicial")
assert (versao == "1.0.0") is False
assert ("1.0.0" == versao) is False
def test_ordem_incompativel_falha_nos_dois_sentidos():
versao = Versao(1, 0, 0, "inicial")
with pytest.raises(TypeError):
versao < "1.0.0"
with pytest.raises(TypeError):
"1.0.0" < versaoExemplo
Imagine uma implementação defeituosa: __eq__ compara apenas (principal, secundaria), mas __lt__ compara (principal, secundaria, correcao).
Então Versao(1, 0, 0, "") == Versao(1, 0, 1, "") seria verdadeiro, mas a primeira também seria menor que a segunda. Isso viola o contrato: valores iguais não podem preceder um ao outro.
Um par pequeno como esse localiza rapidamente quais campos estão divergindo entre __eq__ e __lt__.
Você suspeita que __eq__ esqueceu o campo correcao, enquanto __lt__ continua comparando os três componentes. Quais dois testes você escreveria primeiro para expor esse erro? Inclua também como verificaria o comportamento com uma string incompatível.
Escreva pelo menos 120 caracteres (0/120).

Passo 9 de 9
Conclua uma implementação de referência, execute verificações locais e explique como igualdade, ordem e tipos incompatíveis se comportam.
Nesta prática, os campos principal, secundaria e correcao definem o valor de uma Versao. A nota serve apenas para apresentação: ela não participa de == nem da ordem direta.
O contrato aceita comparações somente entre objetos do mesmo tipo concreto. Fora dele, os métodos retornam NotImplemented. Com total_ordering, __eq__ e __lt__ bastam para disponibilizar as demais relações de ordem.

A ordem própria consulta os componentes numéricos; uma chave externa pode consultar a nota sem alterar o contrato da classe.
No seu computador, crie uma pasta vazia e salve este conteúdo como versao.py. Leia especialmente os dois retornos de NotImplemented: eles delimitam o que a classe sabe comparar.
from functools import total_ordering
@total_ordering
class Versao:
def __init__(self, principal, secundaria, correcao, nota):
self.principal = principal
self.secundaria = secundaria
self.correcao = correcao
self.nota = nota
def __repr__(self):
return (
f"Versao({self.principal}, {self.secundaria}, "
f"{self.correcao}, {self.nota!r})"
)
def __eq__(self, outro):
if type(self) is not type(outro):
return NotImplemented
return (
self.principal,
self.secundaria,
self.correcao,
) == (
outro.principal,
outro.secundaria,
outro.correcao,
)
def __lt__(self, outro):
if type(self) is not type(outro):
return NotImplemented
return (
self.principal,
self.secundaria,
self.correcao,
) < (
outro.principal,
outro.secundaria,
outro.correcao,
)Salve este conteúdo como test_versao.py, na mesma pasta de versao.py. Os testes verificam igualdade de valor, desempate lexicográfico, operadores completados pelo decorador, ordenação por chave e incompatibilidade de tipos.
import pytest
from versao import Versao
def test_igualdade_ignora_nota():
primeira = Versao(1, 2, 3, "publicada")
segunda = Versao(1, 2, 3, "revisada")
assert primeira == segunda
assert not primeira != segunda
def test_ordem_usa_componentes_em_sequencia():
assert Versao(1, 2, 9, "a") < Versao(1, 10, 0, "b")
assert Versao(1, 10, 0, "a") < Versao(2, 0, 0, "b")
def test_total_ordering_completa_operadores():
menor = Versao(1, 0, 0, "inicial")
igual = Versao(1, 0, 0, "mesmo valor")
maior = Versao(1, 0, 1, "correcao")
assert menor <= igual
assert maior > menor
assert maior >= igual
assert not menor > igual
def test_sorted_direto_e_por_chave_externa():
versoes = [
Versao(2, 0, 0, "beta"),
Versao(1, 10, 0, "zeta"),
Versao(1, 2, 9, "alpha"),
]
assert [v.nota for v in sorted(versoes)] == ["alpha", "zeta", "beta"]
assert [v.nota for v in sorted(versoes, key=lambda v: v.nota)] == [
"alpha", "beta", "zeta"
]
def test_tipos_incompativeis():
versao = Versao(1, 2, 3, "estavel")
assert Versao.__eq__(versao, "1.2.3") is NotImplemented
assert Versao.__lt__(versao, "1.2.3") is NotImplemented
assert versao == "1.2.3" is False
assert versao != "1.2.3" is True
with pytest.raises(TypeError):
versao < "1.2.3"Exemplo
No terminal aberto nessa pasta, execute:
python -m pytest -q
Resultado esperado:
5 passed
Se pytest não estiver disponível no seu ambiente, instale-o no ambiente virtual do projeto com python -m pip install pytest e rode o comando novamente.
Após executar o teste, relate o que você observou. Inclua: o efeito de notas diferentes na igualdade, um desempate da ordem lexicográfica, um operador fornecido por total_ordering e a diferença entre == e < ao comparar uma Versao com uma string.
Escreva pelo menos 180 caracteres (0/180).
Resumo
Você reuniu as decisões de comparação em uma implementação verificável.
Agora você pode decidir quando objetos de domínio representam o mesmo valor e quando possuem uma ordem natural. No próximo tutorial, a discussão avança para a coerência entre igualdade e hash.
Parabéns! Você concluiu: Definir igualdade e ordenação entre objetos
Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks