Хеш-коллизии и пользовательский класс: почему объекты пропали из множества
Класс описывает точку, у него переопределено сравнение:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __eq__(self, other):
return (self.x, self.y) == (other.x, other.y)
def __hash__(self):
return hash(self.x)
pts = {Point(1, 1), Point(1, 2), Point(2, 1)}
p = Point(1, 1)
p.x = 5
print(len(pts), p in pts)
Что верно про это множество и про поведение объекта после изменения поля?
- `__hash__` возвращает `hash(self.x)` — это ошибка: одинаковые хеши у разных точек делают множество неработоспособным, `len(pts)` будет 2
- Множество содержит 3 элемента; хеш по одному полю допустим, но замедляет поиск при массовых коллизиях, а изменение поля у объекта делает его ненаходимым в контейнере
- Код упадёт при построении множества: если `__eq__` переопределён, `__hash__` обязан использовать все поля, иначе Python бросает TypeError
- Множество содержит 3 элемента, и `p in pts` вернёт True: поиск в множестве сравнивает объекты через `__eq__`, а хеш используется только для порядка вывода
