blu*_*ote 2 python overloading parameter-passing kwargs
我创建了一个自定义类,我想**
在一个实例上使用运算符将它传递给一个函数.我已经定义__getitem__
和__iter__
,但是当我尝试f(**my_object)
,我得到
`TypeError: argument must be a mapping, not 'MyClass'`
Run Code Online (Sandbox Code Playgroud)
什么是最低要求的方法,以便自定义类有资格作为映射?
**
它不是运算符,它是调用语法的一部分:
如果语法
**expression
出现在函数调用中,则表达式必须求值为映射,其内容被视为附加关键字参数.
因此,如果您的类实现了这些Mapping
方法,那么您应该很高兴.你需要的不仅仅是__getitem__
和__iter__
这里.
阿Mapping
是一个Collection
,所以必须定义至少__getitem__
,__iter__
和__len__
; 除了大部分__contains__
,keys
,items
,values
,get
,__eq__
,和__ne__
可以预期.如果你的自定义类直接继承自的collections.abc.Mapping
,你只需要实现前三个.
演示:
>>> from collections.abc import Mapping
>>> class DemoMapping(Mapping):
... def __init__(self, a=None, b=None, c=None):
... self.a, self.b, self.c = a, b, c
... def __len__(self): return 3
... def __getitem__(self, name): return vars(self)[name]
... def __iter__(self): return iter('abc')
...
>>> def foo(a, b, c):
... print(a, b, c)
...
>>> foo(**DemoMapping(42, 'spam', 'eggs'))
42 spam eggs
Run Code Online (Sandbox Code Playgroud)
如果在调试器下运行它,您将看到Python调用该.keys()
方法,该方法返回一个字典视图,然后__iter__
在迭代视图时委托给自定义类方法.然后通过一系列__getitem__
调用检索这些值.因此,对于您的具体情况,缺少的是.keys()
方法.
另外,请注意Python可能会强制键是字符串!
>>> class Numeric(Mapping):
... def __getitem__(self, name): return {1: 42, 7: 'spam', 11: 'eggs'}[name]
... def __len__(self): return 3
... def __iter__(self): return iter((1, 7, 11))
...
>>> dict(Numeric())
{1: 42, 7: 'spam', 11: 'eggs'}
>>> def foo(**kwargs): print(kwargs)
...
>>> foo(**Numeric())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() keywords must be strings
Run Code Online (Sandbox Code Playgroud)