Requirements for Keyword Argument Unpacking

Viewed 357

What is required to support keyword argument unpacking for a custom class in Python? In both the Python 2.7 and Python 3.6 interpreters the following error message is given when trying to unpack an incompatible type:

>>> dict(**None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: type object argument after ** must be a mapping, not NoneType

Does mapping mean the object has to specifically subclass collections.Mapping? Or is mapping in this case one of those pseudo types such as iterable where you don't have to explicitly subclass collections.Iterable to support iter()? Does this behavior differ between Python 2 and 3?

2 Answers

A Mapping is a generic container for associating key/value pairs.

It is not compulsory to inherit from collections.Mapping in order to use dictionary unpacking. Besides, collections.Mapping is an abstract class, so you'll still have to override some methods in order to be able to use dict unpacking with any of its subclasses.

For an instance of a class to be dict unpackable, it is enough for the class to implement a keys method and a corresponding __getitem__ method to return a value given a key:

class D(object):
  def __getitem__(self, key):
      return 2

  def keys(self):
      return ['1','2','3']

print(dict(**D()))
# {'1': 2, '2': 2, '3': 2}

Here is the Python glossary entry for mapping:

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.

Related