Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a dictonary not have delete methods?

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.

like image 357
Fighter178 Avatar asked Oct 20 '25 07:10

Fighter178


2 Answers

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.

like image 57
Silvio Mayolo Avatar answered Oct 21 '25 22:10

Silvio Mayolo


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.

like image 21
Ian Moote Avatar answered Oct 21 '25 23:10

Ian Moote



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!