我有一个表格的类方法:
def _cool_method(arg1, arg2, **kwargs):
<do pre-processing stuff>
super()._cool_method(**flattened_kwargs)
我希望flattened_kwargs
成为dict
之类的:
flattened_kwargs = {
"arg1": value,
"arg2" value,
"kwargs_key1": value,
"kwargs_key2": {"nestedarg1": value, "nestedarg2": value}
"kwargs_key3": value,
}
在子方法中进行一些处理之后,我需要将单个kwargs dict
传递给超级调用。
我已设法弄清楚如何使用dict
将输入签名压缩为单个locals()
:
attrs = locals().copy()
attrs.pop("kwargs")
attrs.update(kwargs)
我现在想将其转换为辅助函数,以调用许多子类方法。但是,上面的代码假定我知道方法签名定义的**kwargs
的名称。我想从子方法中检查这一点,这样我就不需要将假定的密钥硬编码到pop()
调用中。
据我所知,在Python 3.6中我应该使用inspect并且设法做到这一点:
def _get_signature_kwargs_key(f):
keys = [k for k, v in signature(f).parameters.items() if v.kind == v.VAR_KEYWORD]
return keys[0] if len(keys) == 1 else None
def flatten_signature_args(f, loc):
kwargs_name = _get_signature_kwargs_key(f)
attributes = loc.copy()
# cater for method calls from classes, which include unwanted metadata
for meta in ['__class__', 'self']:
try:
del attributes[meta]
except KeyError:
pass
attributes.pop(kwargs_name)
attributes.update(loc[kwargs_name])
return attributes
由于显而易见的原因,VAR_KEYWORD
唯一性的假设似乎是合理的。但是,有没有更好的方法从签名中提取这个,或者更好的方法来满足我对整体签名展平的要求?
我在调用类方法时也必须执行hack来删除元键,否则当我将self._cool_method
作为输入函数传递时它会失败。
答案 0 :(得分:0)
解决:
def get_signature_locals(f, loc):]
return {k: v for k, v in loc.items() if k in signature(f).parameters}
def get_signature_kwargs_key(f):
keys = [k for k, v in signature(f).parameters.items() if v.kind == v.VAR_KEYWORD]
try:
return keys.pop()
except IndexError:
return None
def flatten_signature_kwargs(func, loc):
kwargs_name = get_signature_kwargs_key(func)
attributes = get_signature_locals(func, loc)
if kwargs_name:
attributes.pop(kwargs_name)
attributes.update(loc[kwargs_name])
return attributes