¿Qué es un objeto de mapeo, según el tipo dict?

La documentación enumera 3 formas de crear una instancia de dict:

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

¿Qué es exactamente un mapeo aquí? ¿Cuál es la interfaz mínima requerida para que dict(mapping) funcione?

Como de costumbre, siéntase libre de leer el código 🙂

Entonces, vamos a 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 */ 

Así que estamos buscando cosas que tengan PyMapping_Keys y PyObject_GetItem . Debido a que somos perezosos, solo usamos el cuadro de búsqueda en los documentos de Python y encontramos el protocolo de mapeo . Entonces, si su CPython PyObject sigue ese protocolo, está listo.

Desde el código fuente de CPython , este comentario:

 /* 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. */ 

Entonces, “la interfaz mínima requerida para que dict (mapeo) funcione” parece ser .keys() y .__getitem__() .

Ejemplo de progtwig:

 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} 

El glosario lo define como:

Un objeto contenedor que admite búsquedas de claves arbitrarias e implementa los métodos especificados en las clases base abstractas Mapping o MutableMapping . Los ejemplos incluyen dict , collections.defaultdict , collections.OrderedDict y collections.Counter .

Así que parece que la lista mínima de métodos para cumplir con la definición es __getitem__ , __iter__ , __len__ , __contains__ , keys , items , values , get , __eq__ y __ne__ . Aunque apuesto que el constructor del dict no necesita realmente todos esos.

Parece que implementar solo keys y __getitem__ es suficiente.

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

Es la mejor respuesta para tu pregunta:

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

Es el ejemplo más simple de mapeo: {}

Si desea crear un tipo de mapeo personalizado, puede heredarlo del dict base y sobrescribir el método mágico __getitem__ (depende de sus necesidades)