¿Por qué los objetos dict son inestables en python?

Quiero decir, ¿por qué no podemos poner clave de dict como dict?

eso significa que no podemos tener el diccionario teniendo la clave como otro diccionario …

Respuesta corta: porque son contenedores mutables .

Si un dict fue hash, su hash cambiaría a medida que cambiara su contenido.

Esto es fácil de tratar. Envuelve un dictado en un frozenset antes de que lo tengas. Luego, cuando necesites usarlo, conviértelo de nuevo a un dict.

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

Tenga en cuenta que el orden de las claves del diccionario no está definido de todos modos, por lo que el cambio en el orden de las claves no importa.

Como han dicho otros, el valor de hash de un dict cambia a medida que cambian los contenidos.

Sin embargo, si realmente necesita usar los dicts como claves, puede hacer una subclase de dict para hacer una versión de hashable.

 >>> 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'} 

Esto reemplaza el valor de hash utilizado para el dictado con la dirección del objeto en la memoria.

Ninguno de los tipos de contenedores mutables en Python son hashable , porque son mutables y, por lo tanto, su valor de hash puede cambiar a lo largo de su vida.

Tal vez por las razones equivocadas me he encontrado con este problema un montón de veces; donde quiero hacer referencia a un dict completo como una clave para algo. No necesito que sea mutable, pero quiero preservar y acceder fácilmente a los miembros del dict .

La forma más fácil que he encontrado para hacer que el dict inmutable y rápidamente utilizable como valor clave es convertirlo en un JSON (o serializar en su alternativa favorita).

Por ejemplo:

 >>> 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'} 

Es fácil de manipular, ya que es solo una cuerda. Y, puede ser serializado en un objeto si desea hacer referencia a sus miembros.