10

I have subclassed the dict and need to detect all its modifications.

(I know I cannot detect an in-place modification of a stored value. That's OK.)

My code:

def __setitem__(self, key, value):
    super().__setitem__(key, value)
    self.modified = True

def __delitem__(self, key):
    super().__delitem__(key)
    self.modified = True

The problem is it works only for a straightforward assignment or deletion. It does not detect changes made by pop(), popitem(), clear() and update().

Why are __setitem__ and __delitem__ bypassed when items are added or deleted? Do I have to redefine all those methods (pop, etc.) as well?

Alex Riley
  • 169,130
  • 45
  • 262
  • 238
VPfB
  • 14,927
  • 6
  • 41
  • 75
  • I have found a related question here: http://stackoverflow.com/questions/7148419/subclass-dict-userdict-dict-or-abc – VPfB Dec 20 '15 at 19:16

2 Answers2

6

For this usage, you should not subclass dict class, but instead use the abstract classes form the collections module of Python standard library.

You should subclass the MutableMapping abstract class and override the following methods: __getitem__, __setitem__, __delitem__, __iter__ and __len__, all that by using an inner dict. The abstract base class ensures that all other methods will use those ones.

class MyDict(collections.MutableMapping):
    def __init__(self):
        self.d = {}
        # other initializations ...

    def __setitem__(self, key, value):
        self.d[key] = value
        self.modified = true
    ...
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Thank you for your suggestion. I tested it. If I subclass from `collections.UserDict` which itself inherits from `MutableMapping`, then my original code works as expected without further modifications. Problem solved. – VPfB Dec 20 '15 at 12:07
1

pop, popitem, clear, update are not implemented through __setitem__ and __delitem__.

You must redefine them also.

I can suggest look at OrderedDict implementation.

Alex Yu
  • 3,412
  • 1
  • 25
  • 38