Immutable Dictionary, Only Use As A Key For Another Dictionary
Solution 1:
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'] # => 1Note 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).
Solution 2:
The Mapping abstract base class makes this easy to implement:
import collections
classImmutableDict(collections.Mapping):
def__init__(self, somedict):
self._dict = dict(somedict) # make a copy
self._hash = Nonedef__getitem__(self, key):
return self._dict[key]
def__len__(self):
returnlen(self._dict)
def__iter__(self):
returniter(self._dict)
def__hash__(self):
if self._hashisNone:
self._hash = hash(frozenset(self._dict.items()))
return self._hashdef__eq__(self, other):
return self._dict == other._dictSolution 3:
I realize this has already been answered, but types.MappingProxyType is an analogous implementation for Python 3.3. Regarding the original question of safety, there is a discussion in PEP 416 -- Add a frozendict builtin type on why the idea of a frozendict was rejected.
Solution 4:
In order for your immutable dictionary to be safe, all it needs to do is never change its hash. Why don't you just disable __setitem__ as follows:
classImmutableDict(dict):
def__setitem__(self, key, value):
raise Exception("Can't touch this")
def__hash__(self):
returnhash(tuple(sorted(self.items())))
a = ImmutableDict({'a':1})
b = {a:1}
print b
print b[a]
a['a'] = 0The output of the script is:
{{'a': 1}: 1}
1Traceback (most recent call last):
File "ex.py", line 11, in <module>
a['a'] = 0
File "ex.py", line 3, in __setitem__
raise Exception("Can't touch this")
Exception: Can't touch thisSolution 5:
Here is a link to pip install-able implementation of @RaymondHettinger's answer: https://github.com/pcattori/icicle
Simply pip install icicle and you can from icicle import FrozenDict!
Update:icicle has been deprecated in favor of maps: https://github.com/pcattori/maps (documentation, PyPI).
Post a Comment for "Immutable Dictionary, Only Use As A Key For Another Dictionary"