I'm working on a project and I have a dictionary in Python. Due to this being an "append-only" dictionary, I need a way to disable .pop, .popitem, .clear, etc. Is this possible in python?
I have tried:
mydict = dict()
#attempt 1:
mydict.pop = None
#Get error pop is read-only
#attempt 2:
del mydict.pop
#Get error pop is read-only
I have tried this on all delete methods with the same results.
Using inheritance to remove functionality violates Liskov substitution (a hypothetical dict subclass would behave erroneously when treated as a dict instance). And besides, I can easily just dict.clear(my_subclassed_dict_instance). The thing you're asking for is not, in Python terminology, a dict and shouldn't masquerade as a subclass of one.
What you're looking for is a fresh class entirely. You want a class that contains a dict, not one that is a dict.
import collections.abc.Mapping
class MyAppendOnlyContainer(Mapping):
def __init__(self, **kwargs):
self._impl = kwargs
def __getitem__(self, key):
return self._impl[key]
def __setitem__(self, key, value):
self._impl[key] = value
def __iter__(self):
return iter(self._impl)
def __len__(self):
return len(self._impl)
# Plus whatever other functionality you need ...
Note that collections.abc.Mapping requires __getitem__, __iter__, and __len__ (which your use case faithfully implements) and gives you get, __contains__, and several other useful dict-like helper functions. What you have is not a dict. What you have is a Mapping with benefits.
Subclass the dict() class:
class NewDict(dict):
def clear(self):
pass
def pop(self, *args): #Note: returns a NoneType
pass
def popitem(self, *args):
pass
Now when you create your dict, create it using:
myDict = NewDict()
I quickly dumped this into the command line interpreter and it seems to work.
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