How to create an immutable dictionary in python?

时间秒杀一切 提交于 2019-12-23 16:07:10

问题


I want to subclass dict in python such that all the dictionaries of the sub-class are immutable.

I don't understand how does __hash__ affects the immutability, since in my understanding it just signifies the equality or non-equality of objects !

So, can __hash__ be used to implement immutability ? How ?

Update:

Objective is that common response from an API is available as a dict, which has to be shared as a global variable. So, that needs to be intact no matter what ?


回答1:


I found an Official reference :

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

Attribution : http://www.python.org/dev/peps/pep-0351/




回答2:


So, can __hash__ be used to implement immutability ?

No, it can't. The object can be made mutable (or not) irrespective of what its __hash__ method does.

The relationship between immutable objects and __hash__ is that, since an immutable object cannot be changed, the value returned by __hash__ remains constant post-construction. For mutable objects, this may or may not be the case (the recommended practice is that such objects simply fail to hash).

For further discussion, see Issue 13707: Clarify hash() constency period.




回答3:


Regarding the relationship between hashability and mutability:

To be useful, a hash implementation needs to fulfil the following properties:

  1. The hash value of two objects that compare equal using == must be equal.

  2. The hash value may not change over time.

These two properties imply that hashable classes cannot take mutable properties into account when comparing instances, and by contraposition that classes which do take mutable properties into account when comparing instances are not hashable. Immutable classes can be made hashable without any implications for comparison.

All of the built-in mutable types are not hashable, and all of the immutable built-in types are hashable. This is mainly a consequence of the above observations.

User-defined classes by default define comparison based on object identity, and use the id() as hash. They are mutable, but the mutable data is not taken into account when comparing instances, so they can be made hashable.

Making a class hashable does not make it immutable in some magic way. On the contrary, to make a dictionary hashable in a reasonable way while keeping the original comparison operator, you will first need to make it immutable.

Edit: Regarding your update:

There are several ways to provide the equivalent of global immutable dictionary:

  1. Use a collections.namedtuple() instance instead.

  2. Use a user-defined class with read-only properties.

  3. I'd usually go with something like this:

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

    By the leading underscore, you make clear that _my_global_dict is an implementation detail not to be touched by application code. Note that this code would still allow to modify dictionary values if they happen to be mutable objects. You could solve this problem by returning copy.copy()s or copy.deepcopy()s of the values if necessary.



来源:https://stackoverflow.com/questions/11014262/how-to-create-an-immutable-dictionary-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!