【问题标题】:What is a mapping object, according to dict type?根据 dict 类型,什么是映射对象?
【发布时间】:2017-04-01 17:09:42
【问题描述】:

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

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

映射到底是什么? dict(mapping) 工作所需的最小接口是什么?

【问题讨论】:

    标签: python dictionary mapping


    【解决方案1】:

    来自the source code for 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(mapping) 工作所需的最小接口”似乎是.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}
    

    【讨论】:

      【解决方案2】:

      glossary 将其定义为:

      支持任意键查找和实现的容器对象 MappingMutableMapping 抽象基中指定的方法 类。示例包括dictcollections.defaultdictcollections.OrderedDictcollections.Counter

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

      【讨论】:

        【解决方案3】:

        似乎只实现keys__getitem__ 就足够了。

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

        【讨论】:

        • 在 3.6 之前仍然有效,也使对象可用于 ** 参数解包。
        【解决方案4】:

        像往常一样,请随意阅读代码:)

        那么,让我们进入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_KeysPyObject_GetItem 的东西。因为我们比较懒,所以我们只使用python文档中的搜索框,找到the mappings protocol。因此,如果您的 CPython PyObject 遵循该协议,那么您就可以开始了。

        【讨论】:

        • 有点惊讶,没有比源代码中的注释更明确地记录这一点。 c-api 映射协议是实现细节,而不是实际的语言规范。
        • 是否official glossary中更明确地记录。
        【解决方案5】:

        这是您问题的最佳答案:

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

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

        如果你想创建一个自定义映射类型,你可以从基础dict继承它并覆盖__getitem__魔术方法(这取决于你的需要)

        【讨论】:

        • 所有dictionaries 都是映射,但并非所有映射都是字典 - 这个问题是询问什么构成映射而不是举例。
        • @TadhgMcDonald-Jensen,那么,我在哪里说过所有映射都是字典?
        • 来自您答案中的链接:“目前只有一种标准映射类型,即字典。”所以唯一的内置映射是dict,根本不是每个映射都必须是一个字典。
        • {} 不是最简单的映射示例。 {} 上面有各种各样的废话
        猜你喜欢
        • 1970-01-01
        • 2019-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-20
        相关资源
        最近更新 更多