问题
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:
The hash value of two objects that compare equal using
==must be equal.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:
Use a
collections.namedtuple()instance instead.Use a user-defined class with read-only properties.
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_dictis 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 returningcopy.copy()s orcopy.deepcopy()s of the values if necessary.
来源:https://stackoverflow.com/questions/11014262/how-to-create-an-immutable-dictionary-in-python