1

I came across this question of trying to implement a dictionary using the collections.abc MutableMapping because I was looking for something similar.

For context, I was looking to implement a dictionary that would out of convenience also act as a mutable object so if I write this for example d = CustomDictionary({'a': 4}) then d.a returns 4.

For reference, here is the code posted by Aaron Hall for this particular problem:

from collections.abc import MutableMapping

class D(MutableMapping):
    '''
    Mapping that works like both a dict and a mutable object, i.e.
    d = D(foo='bar')
    and 
    d.foo returns 'bar'
    '''
    # ``__init__`` method required to create instance from class.
    def __init__(self, *args, **kwargs):
        '''Use the object dict'''
        self.__dict__.update(*args, **kwargs)
    # The next five methods are requirements of the ABC.
    def __setitem__(self, key, value):
        self.__dict__[key] = value
    def __getitem__(self, key):
        return self.__dict__[key]
    def __delitem__(self, key):
        del self.__dict__[key]
    def __iter__(self):
        return iter(self.__dict__)
    def __len__(self):
        return len(self.__dict__)
    # The final two methods aren't required, but nice for demo purposes:
    def __str__(self):
        '''returns simple dict representation of the mapping'''
        return str(self.__dict__)
    def __repr__(self):
        '''echoes class, id, & reproducible representation in the REPL'''
        return '{}, D({})'.format(super(D, self).__repr__(), 
                                  self.__dict__)

However I didn't consider the dangers of doing so. Namely, if I created this custom dictionary class then I would expect to have methods. But what if a method name clashes with a key with the same name? For example:

    def doSomething(self):
        """ A method of CustomDictionary"""
        print("hey!")


d = CustomDictionary()
d['a'] = 3
d['doSomething'] = 4
d.doSomething()

would raise a TypeError: 'int' object is not callable since d.doSomething would return 4 which is not a callable function.

What do you think? How would I go about implementing methods for a custom dictionary class while avoiding this problem.

Unfortunately I couldn't comment on the post since I don't have enough reputation but I was hoping this question deserves its own post.

d34n
  • 52
  • 1
  • 7
  • You'd have to decide what *should* happen if a consumer tries to `__setitem__` for something that already exists. Does this apply only to methods? Only if the new value *isn't* callable (or is otherwise different to the existing value)? – jonrsharpe Jul 07 '20 at 10:40
  • Well ideally, I would leave the basic dictionary functionality as is like the code above, including the `__setitem__` method. I just want to wrap the dictionary in an object which provides more functionality like the `doSomething()` method above. – d34n Jul 08 '20 at 07:56

0 Answers0