wim
wim

Reputation: 363586

What is a mapping object, according to dict type?

The documentation lists 3 ways for creating a dict instance:

class dict(**kwarg)
class dict(mapping, **kwarg)
class dict(iterable, **kwarg)

What exactly is a mapping here? What's the minimal interface required for dict(mapping) to work?

Upvotes: 22

Views: 20037

Answers (5)

Robᵩ
Robᵩ

Reputation: 168876

From the source code for CPython, this comment:

/* We accept for the argument either a concrete dictionary object,
 * or an abstract "mapping" object.  For the former, we can do
 * things quite efficiently.  For the latter, we only require that
 * PyMapping_Keys() and PyObject_GetItem() be supported.
 */

So, "the minimal interface required for dict(mapping) to work" appears to be .keys() and .__getitem__().

Example program:

class M:
    def keys(self):
        return [1,2,3]
    def __getitem__(self, x):
        return x*2

m = M()

d = dict(m)

assert d == {1:2, 2:4, 3:6}

Upvotes: 21

wim
wim

Reputation: 363586

It seems that implementing only keys and __getitem__ is sufficient.

>>> class mydict:
...     def keys(self):
...         return 'xyz'
...     def __getitem__(self, item):
...         return 'potato'
...     
>>> dict(mydict())
{'x': 'potato', 'y': 'potato', 'z': 'potato'}

Upvotes: 4

Marcus Müller
Marcus Müller

Reputation: 36433

As usual, feel free to peruse the code :)

So, let's go into Include/dictobject.h:

132 /* PyDict_Merge updates/merges from a mapping object (an object that
133    supports PyMapping_Keys() and PyObject_GetItem()).  If override is true,
134    the last occurrence of a key wins, else the first.  The Python
135    dict.update(other) is equivalent to PyDict_Merge(dict, other, 1).
136 */

So we're looking for things that have PyMapping_Keys and PyObject_GetItem. Because we're lazy, we just use the search box in the python docs and find the mappings protocol. So if your CPython PyObject follows that protocol, you're good to go.

Upvotes: 2

pivanchy
pivanchy

Reputation: 723

It's the best answer for your question:

https://docs.python.org/2/library/stdtypes.html#typesmapping

It's the simplest example of mapping: {}

If you want to create a custom mapping type, you may inherit it from base dict and overwrite __getitem__ magic method(it depends on your needs)

Upvotes: -1

Peter DeGlopper
Peter DeGlopper

Reputation: 37364

The glossary defines it as:

A container object that supports arbitrary key lookups and implements the methods specified in the Mapping or MutableMapping abstract base classes. Examples include dict, collections.defaultdict, collections.OrderedDict and collections.Counter.

So it looks like the minimal list of methods to meet the definition is __getitem__, __iter__, __len__, __contains__, keys, items, values, get, __eq__, and __ne__. Although I bet the dict constructor does not actually need all of those.

Upvotes: 7

Related Questions