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'] # => 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).
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._dict
Solution 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'] = 0
The 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 this
Solution 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"