从方法签名中获取kwargs的名称,以使用locals()

时间:2018-04-13 10:04:30

标签: python-3.x signature kwargs

我有一个表格的类方法:

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作为输入函数传递时它会失败。

1 个答案:

答案 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