繁体   English   中英

应用'setattr'后如何捕获原始function的arguments?

[英]How to capture arguments of original function after applying 'setattr' to it?

我在一个项目中有一个模块,它先于其他任何内容加载,并且该模块需要将自定义逻辑添加到我从数据库中检索的函数列表中。 要添加此自定义逻辑,我使用内置 python function setattr。

此外,同一项目的人希望为同一列表中的某些功能捕获 arguments。 为了捕获 arguments,他们使用了 inspect.getcallargs function。 但是,他们没有得到原始 function 的 arguments,而是得到了包装器 ZC1C425268E17385D1AB5044 的 arguments。

我理解为什么会发生这种情况,但没有解决问题的方法。

我的装饰器/包装器如下所示:

def func_decorator(func, some_other_params):
    def func_to_return(*args, **kwargs):
        # some code
        payload = func(*args, **kwargs)
        # some other code
        return payload
    return func_to_return

因此,在 function 中遍历要装饰的函数列表,我有如下所示的内容:

def add_custom_logic_to_funcs:
    ....
    for func_name in funcs:
        func = getattr(func_class, func_name)
        setattr(func_class, func_name, func_decorator(func, some_params))

如果假设原始 function 如下所示:

class A:
    def(self, x=None, y=None, z=1):
        #some code

Calling inspect.getcallargs results in returnning {'args': (some object at 0x000000001BCA8C50,), 'kwargs': {}} instead of {'self': some object at 0x000000001BCA8C50, 'x': None, 'y': None ,'z':1}

你将需要两件事 - 首先是你的装饰器本身是用functools.wraps()装饰的,因此装饰的 function 上的一些元数据被添加到装饰的 function 中:

from functools import decorator

def func_decorator(func, some_other_params):
    @wraps(func)
    def func_to_return(*args, **kwargs):
        # some code
        payload = func(*args, **kwargs)
        # some other code
        return payload
    return func_to_return

但是,不要让inspect.getcallargs反映装饰的签名。 取而代之的是,您必须使用inspect.signature - 它返回一个更丰富的Signature object,但它有一个看起来像从.getcallargs返回的.parameters属性:


In [26]: def deco(func): 
    ...:     @wraps(func) 
    ...:     def wrapper(*args, **kw): 
    ...:         return func(*args, **kw) 
    ...:     return wrapper 
    ...:                                                                                                                                                                                       

In [27]: class A: 
    ...:     @deco 
    ...:     def b(self, a, b=2): 
    ...:         pass 
    ...:                                                                                                                                                                                       

In [28]: inspect.signature(A().b).parameters                                                                                                                                                   
Out[28]: mappingproxy({'a': <Parameter "a">, 'b': <Parameter "b=2">})

In [29]: inspect.signature(A.b).parameters                                                                                                                                                     
Out[29]: 
mappingproxy({'self': <Parameter "self">,
              'a': <Parameter "a">,
              'b': <Parameter "b=2">})

暂无
暂无

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

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