Python 类,该类充当**解包的映射
如果不将dict子类化,类需要被视为映射,以便可以通过Python 类,该类充当**解包的映射,python,class,mapping,argument-unpacking,Python,Class,Mapping,Argument Unpacking,如果不将dict子类化,类需要被视为映射,以便可以通过**将其传递给方法 from abc import ABCMeta class uobj: __metaclass__ = ABCMeta uobj.register(dict) def f(**k): return k o = uobj() f(**o) # outputs: f() argument after ** must be a mapping, not uobj 至少在某种程度上,它会抛出缺少映射功能的错误,
**
将其传递给方法
from abc import ABCMeta
class uobj:
__metaclass__ = ABCMeta
uobj.register(dict)
def f(**k): return k
o = uobj()
f(**o)
# outputs: f() argument after ** must be a mapping, not uobj
至少在某种程度上,它会抛出缺少映射功能的错误,这样我就可以开始实现了
我回顾了模拟容器类型,但简单地定义魔术方法没有效果,使用ABCMeta
重写并注册为dict将断言验证为子类,但失败isinstance(o,dict)
。理想情况下,我甚至不想使用ABCMeta
方法\uu 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将为您实现所有其他功能:
\uuuuu包含
,键
,项
,值
,获取
,\uuuuuuuuuuu情商
,以及通过挖掘源代码可以找到答案
尝试将非映射对象与**
一起使用时,会出现以下错误:
TypeError: 'Foo' object is not a mapping
如果我们搜索CPython的错误源,我们可以找到:
关键部分是:
对于后者,我们只要求支持PyMapping_Keys()和PyObject_GetItem()
超出范围,但具有相关性和信息量,谢谢有用。这已经转移到了collections.abc软件包中:@StuartBuckingham我感谢你的谦虚,但下次请随意编辑我的答案:)啊,我不知道这是可能的。谢谢@Neig
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;