В ответ на ваши вопросы в комментариях, вот пример, показывающий, почему изменяемые типы обычно плохая идея для словарных ключей:
class MutableIntKey:
def __init__(self, val):
self.val = val
def __eq__(self, other):
return self.val == other.val
def __hash__(self):
return self.val
k = MutableIntKey(5)
d = {k: "Five"}
print(d) # {<__main__.MutableIntKey object at 0x00000249DFBFA400>: 'Five'}
print(k in d) # True
Пока все работает, но что еслиключ видоизменен ...
# Mutate k
k.val = 600
print(d) # {<__main__.MutableIntKey object at 0x00000249DFBFA400>: 'Five'}
print(k in d) # False
Теперь словарь не «думает», что ключ присутствует в словаре.
Но на самом деле ключ - это там ...
print(k in list(d.keys())) # True
Теперь сделать пользовательский объект неизменяемым - не самая простая вещь в мире, но на самом деле вас волнует, что ключ dict неизменен.В частности, вы хотите убедиться, что свойства вашего ключа DICT, которые используются в __hash__
и __eq__
, являются неизменяемыми или каким-либо иным образом защищены от изменений.
Самый простой, но наименее гибкий подход заключается в использованииссылаться на равенство в качестве теста __eq__
(по умолчанию) и использовать id(self)
для реализации __hash__
.Это гарантирует, что даже в случае мутации ключ будет найден.Недостатком является то, что единственный способ поиска ключа в словаре - это если у вас уже есть ссылка на этот точный объект.
Другой способ - просто не изменять объект, который вы используете для ключа послеты где-то использовал его для ключа.Возможно, не самый интуитивный или надежный, но, безусловно, сработает.
Другой способ - создать неизменный объект, используя соответствующее пользовательское состояние объекта, и использовать его в качестве ключа.Небольшая трата памяти, но простая и выполняющая работу.
Другой способ - использовать дескрипторы важных атрибутов (которые оцениваются как часть методов __eq__
и __hash__
) для предотвращенияих легко изменить.
Я уверен, что есть много других подходов, поэтому очень важно, чтобы вы знали о процессе поиска ключей в словаре.