Почему объекты dict не сотрясаются в python?

Я имею в виду, почему мы не можем поставить ключ dict в качестве dict?

это означает, что мы не можем иметь словарь, имеющий ключ в качестве другого словаря...

Ответ 1

Короткий ответ: поскольку они являются изменяемыми контейнерами.

Если dict был хэширован, его хэш изменился бы при изменении его содержимого.

Ответ 2

С этим легко справиться. Оберните диктофон в frozenset, прежде чем вы его сделаете. Затем, когда вам нужно использовать его, преобразуйте его обратно в dict.

>>> unhashable = {'b': 'a', 'a': 'b'}
>>> hashable = frozenset(unhashable.items())
>>> unhashable = dict(hashable)
>>> unhashable
{'a': 'b', 'b': 'a'}

Обратите внимание, что порядок словарных букв undefined в любом случае, поэтому изменение порядка клавиш не имеет значения.

Ответ 3

Как говорили другие, хеш-значение dict изменяется при изменении содержимого.

Однако, если вам действительно нужно использовать dicts как ключи, вы можете подклассифицировать dict, чтобы сделать хеширующую версию.

>>> class hashabledict(dict):
...    def __hash__(self):
...        return id(self)
... 
>>> hd = hashabledict()
>>> d = dict()
>>> d[hd] = "foo"
>>> d
{{}: 'foo'}

>>> hd["hello"] = "world"
>>> d
{{'hello': 'world'}: 'foo'}

Это заменяет хеш-значение, используемое для dict с адресом объекта в памяти.

Ответ 4

Ни один из изменяемых типов контейнеров в Python не является hashable, поскольку они изменяемы и, следовательно, их хэш-значение может меняться в течение их жизни.

Ответ 5

Возможно, неправильные причины я столкнулся с этой проблемой несколько раз; где я хочу указать полный dict как ключ к чему-то. Мне не нужно, чтобы он изменялся, но я хочу сохранить и легко получить доступ к членам dict.

Самый простой способ, с помощью которого dict неизменный и быстро используемый в качестве ключевого значения, - сделать его JSON (или сериализовать в вашей любимой альтернативе).

Например:

>>> import json
>>> d = {'hey':1, 'there':2}
>>> d_key = json.dumps(d)
>>> d_key
'{"there": 2, "hey": 1}'
>>> d2 = {d_key: 'crazytown'}
>>> d2
{'{"there": 2, "hey": 1}': 'crazytown'}

Легко манипулировать, так как это просто строка. И его можно де-сериализовать в объект, если вы хотите ссылаться на его члены.