¿Cómo crear un diccionario inmutable en python?

Quiero subclass dict en python de tal manera que todos los diccionarios de la subclase sean inmutables.

No entiendo cómo __hash__ afecta a la inmutabilidad, ya que, según tengo entendido, ¡solo significa la igualdad o no igualdad de los objetos!

Entonces, ¿se puede usar __hash__ para implementar la inmutabilidad? Cómo ?

Actualización :

El objective es que la respuesta común de una API está disponible como un dict, que debe compartirse como una variable global. Entonces, ¿eso tiene que estar intacto sin importar qué?

He encontrado una referencia oficial:

 class imdict(dict): def __hash__(self): return id(self) def _immutable(self, *args, **kws): raise TypeError('object is immutable') __setitem__ = _immutable __delitem__ = _immutable clear = _immutable update = _immutable setdefault = _immutable pop = _immutable popitem = _immutable 

Atribución: http://www.python.org/dev/peps/pep-0351/

Entonces, ¿se puede usar __hash__ para implementar la inmutabilidad?

No, no puede. El objeto puede ser mutable (o no) independientemente de lo que __hash__ su método __hash__ .

La relación entre los objetos inmutables y __hash__ es que, dado que un objeto inmutable no se puede cambiar, el valor devuelto por __hash__ permanece constante después de la construcción. Para objetos mutables, este puede o no ser el caso (la práctica recomendada es que tales objetos simplemente no se pueden hash).

Para obtener más información, consulte el Número 13707: Aclarar el período de constancia de hash() .

Respecto a la relación entre hashabilidad y mutabilidad:

Para ser útil, una implementación de hash debe cumplir las siguientes propiedades:

  1. El valor de hash de dos objetos que comparan igual usando == debe ser igual.

  2. El valor de hash no puede cambiar con el tiempo.

Estas dos propiedades implican que las clases de hashable no pueden tomar en cuenta las propiedades mutables al comparar instancias, y por contraposición a las clases que sí tienen en cuenta las propiedades mutables cuando se comparan instancias no son hashables. Las clases inmutables pueden hacerse hashable sin ninguna implicación para la comparación.

Todos los tipos mutables incorporados no son hashable, y todos los tipos incorporados inmutables son hashable. Esto es principalmente una consecuencia de las observaciones anteriores.

Las clases definidas por el usuario de forma predeterminada definen la comparación en función de la identidad del objeto y utilizan el id() como hash. Son mutables, pero los datos mutables no se tienen en cuenta al comparar instancias, por lo que se pueden convertir en hashable.

Hacer un hashable de clase no lo hace inmutable de alguna manera mágica. Por el contrario, para que un diccionario se pueda marcar de una manera razonable manteniendo el operador de comparación original, primero deberá hacerlo inmutable.

Editar : Con respecto a su actualización:

Hay varias formas de proporcionar el equivalente de un diccionario global inmutable:

  1. Use una instancia de collections.namedtuple() lugar.

  2. Utilice una clase definida por el usuario con propiedades de solo lectura.

  3. Normalmente voy con algo como esto:

     _my_global_dict = {"a": 42, "b": 7} def request_value(key): return _my_global_dict[key] 

    Por el subrayado principal, deja en claro que _my_global_dict es un detalle de implementación que no debe ser tocado por el código de la aplicación. Tenga en cuenta que este código todavía permitiría modificar los valores del diccionario si resultan ser objetos mutables. Puede resolver este problema devolviendo copy.copy() o copy.deepcopy() s de los valores si es necesario.