У меня возникла необходимость в реализации хэшируемого dict, чтобы я мог использовать словарь в качестве ключа для другого словаря.
Несколько месяцев назад я использовал эту реализацию: Python hashable dicts
Однако я получил известие от коллеги, сказав: "На самом деле это не является неизменным, поэтому это небезопасно. Вы можете использовать его, но это заставляет меня чувствовать себя грустным Panda.
Итак, я начал искать вокруг, чтобы создать неизменную. Мне не нужно сравнивать "ключ-dict" с другим "ключ-dict". Его единственное использование - это ключ для другого словаря.
Я придумал следующее:
class HashableDict(dict):
"""Hashable dict that can be used as a key in other dictionaries"""
def __new__(self, *args, **kwargs):
# create a new local dict, that will be used by the HashableDictBase closure class
immutableDict = dict(*args, **kwargs)
class HashableDictBase(object):
"""Hashable dict that can be used as a key in other dictionaries. This is now immutable"""
def __key(self):
"""Return a tuple of the current keys"""
return tuple((k, immutableDict[k]) for k in sorted(immutableDict))
def __hash__(self):
"""Return a hash of __key"""
return hash(self.__key())
def __eq__(self, other):
"""Compare two __keys"""
return self.__key() == other.__key() # pylint: disable-msg=W0212
def __repr__(self):
"""@see: dict.__repr__"""
return immutableDict.__repr__()
def __str__(self):
"""@see: dict.__str__"""
return immutableDict.__str__()
def __setattr__(self, *args):
raise TypeError("can't modify immutable instance")
__delattr__ = __setattr__
return HashableDictBase()
Для проверки функциональности я использовал следующее:
d = {"a" : 1}
a = HashableDict(d)
b = HashableDict({"b" : 2})
print a
d["b"] = 2
print a
c = HashableDict({"a" : 1})
test = {a : "value with a dict as key (key a)",
b : "value with a dict as key (key b)"}
print test[a]
print test[b]
print test[c]
который дает:
{'a': 1}
{'a': 1}
значение с ключом dict (ключ a)
значение с ключом dict (ключ b)
значение с помощью ключа dict (клавиша a)
как вывод
Является ли это "наилучшим возможным" неизменным словарем, который я могу использовать, который удовлетворяет моим требованиям? Если нет, то что было бы лучшим решением?