Python 类,该类充当**解包的映射

Python 类,该类充当**解包的映射,python,class,mapping,argument-unpacking,Python,Class,Mapping,Argument Unpacking,如果不将dict子类化,那么类需要被视为映射,以便可以通过**将其传递给方法 至少在某种程度上,它会抛出缺少映射功能的错误,这样我就可以开始实现了 我回顾了模拟容器类型,但简单地定义magic方法没有效果,使用ABCMeta重写并注册为dict将断言验证为子类,但在instanceo,dict中失败。理想情况下,我甚至不想使用ABCMeta。使用u getitem_uuuuuuuuuuu和keys方法就足够了: >>> class D: def keys(sel

如果不将dict子类化,那么类需要被视为映射,以便可以通过**将其传递给方法

至少在某种程度上,它会抛出缺少映射功能的错误,这样我就可以开始实现了

我回顾了模拟容器类型,但简单地定义magic方法没有效果,使用ABCMeta重写并注册为dict将断言验证为子类,但在instanceo,dict中失败。理想情况下,我甚至不想使用ABCMeta。

使用u getitem_uuuuuuuuuuu和keys方法就足够了:

>>> class D:
        def keys(self):
            return ['a', 'b']
        def __getitem__(self, key):
            return key.upper()


>>> def f(**kwds):
        print kwds


>>> f(**D())
{'a': 'A', 'b': 'B'}

如果您试图创建一个映射,而不仅仅是满足传递给函数的要求,那么您真的应该从collections.abc.Mapping继承。如中所述,您只需实现:

__getitem__
__len__
__iter__

Mixin将为您实现所有其他功能:uuu包含uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

尝试将非映射对象与**一起使用时,会出现以下错误:

TypeError: 'Foo' object is not a mapping
如果我们搜索CPython的错误源,我们可以找到:

关键部分是:

对于后者,我们只要求支持PyMapping_键和PyObject_GetItem


超出范围,但具有相关性和信息量,谢谢有用。这已经转移到collections.abc软件包中:@StuartBuckingham我感谢你的谦虚,但下次请随意编辑我的答案:啊,我不知道这是可能的。谢谢@Neig
TypeError: 'Foo' object is not a mapping
case TARGET(DICT_UPDATE): {
    PyObject *update = POP();
    PyObject *dict = PEEK(oparg);
    if (PyDict_Update(dict, update) < 0) {
        if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
            _PyErr_Format(tstate, PyExc_TypeError,
                            "'%.200s' object is not a mapping",
                            Py_TYPE(update)->tp_name);
/* 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.
 */
if (a == NULL || !PyDict_Check(a) || b == NULL) {
    PyErr_BadInternalCall();
    return -1;