I have a dictionary filled with key-object pairs. I want to make the dictionary immutable and I thought the best/easiest way is to cast it to a frozenset but frozenset(dict) and also tuple(dict) only stores the keys.
Using frozenset(dict.items()) I seem to get a frozenset with the key-object pairs but I don't know how to retrieve the values/keys.
I have the following code which works, as long as "__obfuscators" is a dictionary
def obfuscate_value(self, key, value):
obfuscator = self.__obfuscators.get(key)
if obfuscator is not None:
return obfuscator.obfuscate_value(value)
else:
return value
I tried this in an attempt to get it working with the frozen set:
def obfuscate_value(self, key, value):
try:
obfuscator = self.__obfuscators[key]
except:
return value
return obfuscator.obfuscate_value(value)
but this gives that frozenset does not have \__getitem__
and self.__obfuscators.__getattribute__(key) always says it does not have the attribute (because I assume this searches for a function named key)
Is there a better way to make the dictionary immutable or how can I retrieve the object depending on the key?
Edit:
I ended up casting the dict to a tuple using tuple(obfuscator.items())
and then wrote my own find value function:
def find_obfuscator(self, key):
for item in self.__obfuscators:
x, y = item
if self.case_insensitive:
if x.lower() == key.lower():
return y
else:
if x == key:
return y
I would like to thank everyone for their efforts and input.
You can create an immutable view of a dictionary using types.MappingProxyType:
from types import MappingProxyType
d = { 'a': 1 }
fd = MappingProxyType(d)
fd['a']
#output:
1
fd['a'] = 2
#output:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'mappingproxy' object does not support item assignment
notice that you can still change the vaule object, so:
d = { 'a': [1] }
fd = MappingProxyType(d)
fd['a'].append(2)
fd['a']
#output:
[1,2]
will work.
The simplest way I could think of to achieve what you want was to subclass the standard dict type and overwrite its __setitem__ method:
class MyDict(dict):
def __setitem__(self, key, value):
raise NotImplementedError("This is a frozen dictionary")
This allows you to create dictionaries that cannot thereafter be changed by item assignment:
d = MyDict({1: 2, 3: 4})
or, equivalently:
d = MyDict([(1, 2), (3, 4)])
The dict then prints out just like a standard dict:
{1: 2, 3: 4}
But when you try to change a value (or add a new one):
d[1] = 15
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-21-a22420992053> in <module>()
----> 1 d[1] = 34
<ipython-input-18-03f266502231> in __setitem__(self, key, value)
1 class MyDict(dict):
2 def __setitem__(self, key, value):
----> 3 raise NotImplementedError("This is a frozen dictionary")
NotImplementedError: This is a frozen dictionary
Note that this isn't fully immutable, however:
d.update({1:17})
for example, will update it, but this solution might be good enough - it depends on the broader requirements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With