20

I'm using python-spidermonkey, which internally uses PyMapping_Check to identify if the object being used as a global (in rt.new_context(global)) implements the mapping protocol. (This is basically a dictionary passed to python-spidermonkey so that javascript has limited access to python variables.)

There's no official definition I could find of the mapping protocol in Python, so I've been using trial and error to determine what's in it. Is there an official reference?

Chris
  • 5,876
  • 3
  • 43
  • 69

1 Answers1

31

The collections.abc module defines the interfaces for things like Mapping, Sequence, and so on.

By inheriting from the abstract base classes in that module, you get default implementations of some of the methods. So to be considered a Mapping, your class definition should look something like this:

class MyMapping(collections.abc.Mapping):
    def __getitem__(self, key):
        pass
    def __iter__(self):
        pass
    def __len__(self):
        pass

Inheriting from Mapping will get you 'free' implementations of most of dict's useful methods:

  • __contains__
  • keys
  • items
  • values
  • get
  • __eq__
  • __ne__

If these default method implementations are inefficient with your custom data structure, you can always override them with your own versions.


To be considered a MutableMapping, your class's interface should look like this:

class MyMutableMapping(collections.abc.MutableMapping):
    def __getitem__(self, key):
        pass
    def __setitem__(self, key, item):
        pass
    def __delitem__(self, key):
        pass
    def __iter__(self):
        pass
    def __len__(self):
        pass

Inheriting from MutableMapping gets you 'free' definitions of all of Mapping's methods, plus:

  • pop
  • popitem
  • clear
  • update
  • setdefault

If you're 'rolling your own' from scratch and don't want to use an abstract base class, you should probably try to define all of the above methods, if you want your class to be strictly Liskov-substitutable for dict.

ddaa
  • 52,890
  • 7
  • 50
  • 59
Benjamin Hodgson
  • 42,952
  • 15
  • 108
  • 157
  • This seems correct, thanks! I wish they had used the keyword mapping protocol anywhere on that page. – Chris Nov 04 '13 at 19:47
  • 1
    You can also use `collections.Mapping.register(MyMappingLikeClass)` if you know that you've implemented enough of the mapping protocol for your specific use, but not enough to pass the regular mapping checks. – Blckknght Nov 04 '13 at 21:02
  • @Blckknght: what are the "regular mapping checks"? – Mr_and_Mrs_D Mar 31 '17 at 14:11
  • I believe the `__setitem__` signature should be `def __setitem__(self, item, value)` for MutabeMapping. – bicarlsen Dec 15 '19 at 20:09
  • Should __iter__(self) return a iterator over (key,value) pairs, or only keys? Is the order important? I could not find these details in the documentation. – Fırat Kıyak Mar 10 '22 at 18:54