Médio Python
Igualdade e Hash para Ponto
Enunciado
Implemente uma classe Ponto que representa um ponto no plano cartesiano com coordenadas x e y. Defina __eq__ para que dois pontos sejam iguais se tiverem as mesmas coordenadas, e __hash__ consistente. Depois, crie um conjunto com alguns pontos e verifique se um ponto duplicado é reconhecido como já existente.
Requisitos
- A classe
Pontodeve ter__init__,__eq__e__hash__. __eq__deve retornarTrueapenas se ambos os objetos forem instâncias dePontoe tiveremxeyiguais.__hash__deve ser baseado na tupla(x, y).- O programa deve criar um
setcom pontos e demonstrar que um ponto com mesmas coordenadas não é adicionado novamente.
Código inicial
class Ponto:
def __init__(self, x, y):
self.x = x
self.y = y
# Implemente __eq__ e __hash__
# Teste
p1 = Ponto(1, 2)
p2 = Ponto(1, 2)
p3 = Ponto(3, 4)
print(p1 == p2) # True
print(len({p1, p2, p3})) # 2
Saída esperada
True
2
Ver dica
Use isinstance(other, Ponto) para garantir que a comparação só ocorra entre pontos. Para o hash, use hash((self.x, self.y)).
Mostrar solução
class Ponto:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
if not isinstance(other, Ponto):
return NotImplemented
return self.x == other.x and self.y == other.y
def __hash__(self):
return hash((self.x, self.y))
p1 = Ponto(1, 2)
p2 = Ponto(1, 2)
p3 = Ponto(3, 4)
print(p1 == p2)
print(len({p1, p2, p3}))
Passo a passo
- Definimos a classe
Pontocom__init__que guardaxey. __eq__verifica seotheré uma instância dePonto; se não for, retornaNotImplementedpara permitir que o Python tente a comparação reversa.- Se for um
Ponto, compara as coordenadas e retorna um booleano. __hash__retorna o hash da tupla(x, y), garantindo que pontos iguais tenham o mesmo hash.- Criamos três pontos:
p1ep2iguais,p3diferente. - Imprimimos
p1 == p2(True) e o comprimento do conjunto{p1, p2, p3}(2), poisp2é considerado duplicata.
Por que funciona
O conjunto usa __hash__ para determinar o balde (bucket) e __eq__ para verificar igualdade dentro do balde. Como p1 e p2 têm o mesmo hash e são iguais, o conjunto os trata como o mesmo elemento. Isso é essencial para usar objetos como chaves de dicionário ou membros de conjuntos.
Erros comuns
- Esquecer de implementar
__hash__ao definir__eq__: Python 3 torna a classe não hashable, e usá-la em um set lançaTypeError: unhashable type: 'Ponto'. - Implementar
__hash__baseado em atributos mutáveis: sexouymudarem, o hash muda e o objeto se perde em coleções. Use atributos imutáveis. - Não verificar o tipo em
__eq__: comparar com um inteiro pode causarAttributeErrorse tentar acessar.x.
Outra forma de resolver
Podemos usar @dataclass(frozen=True) para gerar automaticamente __eq__ e __hash__. Exemplo:
from dataclasses import dataclass
@dataclass(frozen=True)
class Ponto:
x: int
y: int
Isso é preferível quando a classe é simples e imutável.
Saída esperada
True
2