Для двух показанных объектов код уже оставляет одну запись со значением 'second'. Реальная проблема — изменяемый список внутри ключа и слабый hash(sum(...)); храните неизменяемый кортеж и хешируйте его.
Обновление значений в словаре при совпадении пользовательских ключей
Для двух показанных объектов код уже оставляет одну запись со значением 'second'. Реальная проблема — изменяемый список внутри ключа и слабый hash(sum(...)); храните неизменяемый кортеж и хешируйте его.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо исправить реализацию класса HashList, чтобы два объекта с одинаковым набором чисел считались равными и при добавлении в словарь один заменял другой.
from typing import Any
class HashList:
def __init__(self, data: list[int]) -> None:
self._data = data
def __eq__(self, other: Any) -> bool:
if isinstance(other, self.__class__):
return self._data == other._data
return False
def __hash__(self) -> int:
return hash(sum(self._data))
obj1 = HashList([1, 2, 3])
obj2 = HashList([1, 2, 3])
my_dict = {
obj1: "first",
obj2: "second",
}
print(my_dict)
Ответ
Для двух показанных объектов код уже оставляет одну запись со значением 'second'. Реальная проблема — изменяемый список внутри ключа и слабый hash(sum(...)); храните неизменяемый кортеж и хешируйте его.
Простой вариант:
from dataclasses import dataclass
@dataclass(frozen=True)
class HashList:
_data: tuple[int, ...]
def __init__(self, data):
object.__setattr__(self, '_data', tuple(data))
Автоматические eq/hash сравнивают и хешируют последовательность целиком. Порядок значим, как и в исходном сравнении списков. Если требуется математическое множество, это другой контракт. Одинаковая сумма разных списков не нарушает корректность словаря сама по себе: коллизии допустимы, но ухудшают распределение. Изменение хеша уже вставленного ключа действительно ломает поиск.