繁体   English   中英

如何以与 inspect.signature 一起使用的方式包装 python 函数?

[英]How can I wrap a python function in a way that works with with inspect.signature?

一些没有争议的背景实验:

import inspect

def func(foo, bar):
  pass

print(inspect.signature(func))  # Prints "(foo, bar)" like you'd expect

def decorator(fn):
  def _wrapper(baz, *args, *kwargs):
    fn(*args, **kwargs)

  return _wrapper

wrapped = decorator(func)
print(inspect.signature(wrapped))  # Prints "(baz, *args, **kwargs)" which is totally understandable

问题

如何实现我的装饰器以便print(inspect.signature(wrapped))吐出“(baz, foo, bar)”? 我可以通过添加传入的任何fn的参数,然后将baz粘贴到列表上,以某种方式动态构建_wrapper吗?

答案不是

def decorator(fn):
  @functools.wraps(fn)
  def _wrapper(baz, *args, *kwargs):
    fn(*args, **kwargs)

  return _wrapper

再次给出“(foo,bar)” - 这是完全错误的。 调用wrapped(foo=1, bar=2)是一个类型错误 - “缺少 1 个必需的位置参数:'baz'”

我觉得没必要这么迂腐,但是

def decorator(fn):
  def _wrapper(baz, foo, bar):
    fn(foo=foo, bar=bar)

  return _wrapper

也不是我正在寻找的答案 - 我希望装饰器适用于所有功能。

您可以使用__signature__ ( PEP ) 属性来修改包装对象的返回签名。 例如:

import inspect


def func(foo, bar):
    pass


def decorator(fn):
    def _wrapper(baz, *args, **kwargs):
        fn(*args, **kwargs)

    f = inspect.getfullargspec(fn)

    fn_params = []
    if f.args:
        for a in f.args:
            fn_params.append(
                inspect.Parameter(a, inspect.Parameter.POSITIONAL_OR_KEYWORD)
            )

    if f.varargs:
        fn_params.append(
            inspect.Parameter(f.varargs, inspect.Parameter.VAR_POSITIONAL)
        )

    if f.varkw:
        fn_params.append(
            inspect.Parameter(f.varkw, inspect.Parameter.VAR_KEYWORD)
        )

    _wrapper.__signature__ = inspect.Signature(
        [
            inspect.Parameter("baz", inspect.Parameter.POSITIONAL_OR_KEYWORD),
            *fn_params,
        ]
    )
    return _wrapper


wrapped = decorator(func)
print(inspect.signature(wrapped))

印刷:

(baz, foo, bar)

如果函数是:

def func(foo, bar, *xxx, **yyy):
    pass

然后print(inspect.signature(wrapped))打印:

(baz, foo, bar, *xxx, **yyy)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM