Immutable dictionary, only use as a key for another dictionary
The Mapping abstract base class makes this easy to implement:
import collections
class ImmutableDict(collections.Mapping):
def __init__(self, somedict):
self._dict = dict(somedict) # make a copy
self._hash = None
def __getitem__(self, key):
return self._dict[key]
def __len__(self):
return len(self._dict)
def __iter__(self):
return iter(self._dict)
def __hash__(self):
if self._hash is None:
self._hash = hash(frozenset(self._dict.items()))
return self._hash
def __eq__(self, other):
return self._dict == other._dict
If you are only using it as a key for another dict
, you could go for frozenset(mutabledict.items())
. If you need to access the underlying mappings, you could then use that as the parameter to dict
.
mutabledict = dict(zip('abc', range(3)))
immutable = frozenset(mutabledict.items())
read_frozen = dict(immutable)
read_frozen['a'] # => 1
Note that you could also combine this with a class derived from dict
, and use the frozenset
as the source of the hash, while disabling __setitem__
, as suggested in another answer. (@RaymondHettinger's answer for code which does just that).