Вопрос проверяет понимание того, как работает хеширование пользовательских объектов в Python по умолчанию и как это влияет на их использование в словарях и множествах.
В Python каждый объект может иметь хеш-значение, которое используется для быстрого сравнения в словарях и множествах. Для пользовательских классов, если вы не переопределяете __hash__(), он наследуется от базового класса object. Реализация по умолчанию использует id() объекта — уникальный идентификатор, связанный с его адресом в памяти. Это гарантирует, что каждый экземпляр имеет уникальный хеш, но делает невозможным сравнение по содержимому.
Из-за этого два разных объекта с одинаковыми атрибутами будут считаться разными ключами в словаре или элементами множества. Например:
class Person:
def __init__(self, name):
self.name = name
p1 = Person('Alice')
p2 = Person('Alice')
print(hash(p1) == hash(p2)) # False
print(p1 == p2) # False (по умолчанию сравниваются id)Если вы переопределяете __eq__() для сравнения по содержимому, Python автоматически устанавливает __hash__ в None, чтобы предотвратить использование объектов в хеш-таблицах, так как это может нарушить контракт (равные объекты должны иметь равные хеши). Чтобы сделать объект хешируемым, нужно явно определить __hash__(), обычно на основе тех же атрибутов, что и в __eq__.
Понимание поведения __hash__ по умолчанию важно для корректного использования пользовательских объектов в словарях и множествах. Если вам нужно сравнивать объекты по значению, всегда переопределяйте __eq__ и __hash__ вместе, чтобы сохранить консистентность.