问题 什么是映射对象,根据dict类型?


文件 列出了创建dict实例的3种方法:

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

究竟是什么 制图 这里?什么是所需的最小接口 dict(mapping) 上班?


11704
2017-11-17 23:48


起源



答案:


CPython的源代码,这个评论:

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

因此,“dict(映射)工作所需的最小接口”似乎是 .keys() 和 .__getitem__()

示例程序:

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}

8
2017-11-18 00:05



谢谢,我已经通过压倒自己找到了它 __getattr__ 并打印查找的名称。但是拥有源代码链接是件好事。 - wim


答案:


CPython的源代码,这个评论:

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

因此,“dict(映射)工作所需的最小接口”似乎是 .keys() 和 .__getitem__()

示例程序:

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}

8
2017-11-18 00:05



谢谢,我已经通过压倒自己找到了它 __getattr__ 并打印查找的名称。但是拥有源代码链接是件好事。 - wim


词汇表 将其定义为:

一个容器对象,支持任意键查找和实现   中指定的方法 制图 要么 MutableMapping 抽象基础   类。例子包括 dictcollections.defaultdict,    collections.OrderedDict 和 collections.Counter

所以看起来满足定义的最小方法列表是 __getitem____iter____len____contains__keysitemsvaluesget__eq__,和 __ne__。虽然我打赌dict构造函数实际上并不需要所有这些。


4
2017-11-17 23:54





似乎只是实施 keys 和 __getitem__ 足够了。

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

2
2017-11-18 00:06



仍然有效高达3.6,也使该对象可用 ** 参数拆包。 - Tadhg McDonald-Jensen
哦谢谢。我将从问题中删除2.7标签。 - wim


像往常一样,随时仔细阅读代码:)

那么,让我们进入 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 */

所以我们正在寻找具有的东西 PyMapping_Keys 和 PyObject_GetItem。因为我们很懒,所以我们只需使用python文档中的搜索框即可找到 映射协议。因此,如果您的CPython PyObject遵循该协议,那么您很高兴。


0
2017-11-18 00:09



有点惊讶这没有比源代码中的注释更明确地记录。 c-api映射协议是实现细节,而不是实际的语言规范。 - wim


这是您问题的最佳答案:

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

这是最简单的映射示例: {}

如果要创建自定义映射类型,可以从base继承它 dict 并覆盖 __getitem__ 魔法(取决于你的需要)


-1
2017-11-18 00:02



所有 dictionaries是映射,但并非所有映射都是字典 - 这个问题是在询问 是什么构成了映射 不要求举个例子。 - Tadhg McDonald-Jensen
@ TadhgMcDonald-Jensen,所以,我告诉所有映射都是dicts? - pivanchy
从你的答案中的链接:“目前只有一种标准的映射类型,字典。”所以唯一的内置映射是 dict,根本不是每个映射都必须是dict。 - Tadhg McDonald-Jensen
{} 不是最简单的映射示例。 {} 还有各种各样的废话 - wim