簡體   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