从方法签名中获取 kwargs 的名称,以使用 locals() 将方法签名展平为单个字典

Get name of kwargs from method signature to flatten a method signature into a single dict using locals()

我有一个 class 形式的方法:

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 传递给超级调用。

我已经设法弄清楚如何使用 locals():

将输入签名扁平化为单个 dict
attrs = locals().copy()
attrs.pop("kwargs")
attrs.update(kwargs)

我现在想将其转换为辅助函数以调用多个子 class 方法。但是,上面的代码假定我知道方法签名定义的 **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 唯一性的假设似乎是合理的。但是,是否有更好的方法从签名中提取它,或者是否有更好的方法来满足我对整体签名进行展平的要求?

我还必须在调用 class 方法时进行破解以删除元键,或者当我将 self._cool_method 作为输入函数传递时它会失败。

解决方法:

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