如何在字典中捕获函数的输入参数

How to catch the input argument of a function in a dict

出于记录目的,我尝试自动捕获传递给此函数内部函数的参数,并将它们转换为 arg : value 的字典。 我尝试了 inspect.signature() 模块,但它只提供函数的默认输入,而不是传递给它的参数

import inspect

def my_add_func(a, b ,c=3):
    sig = inspect.signature(my_add_func)
    print("my_add_func args : {0}".format(sig))
    return a + b + c

if __name__ == '__main__':
    my_add_func(10, 2, 3)

输出:

(a, b, c=3)

而我想要:

{a: 10, b: 2, c:3}

我该怎么做?

您可以使用 signature.bind:

import inspect

def my_add_func(a, b ,c=3):
    sig = inspect.signature(my_add_func)
    print("my_add_func args : {0}".format(sig.bind(a, b, c)))  # changed here
    return a + b + c

if __name__ == '__main__':
    my_add_func(10, 2, 3)

给出:

my_add_func args : <BoundArguments (a=10, b=2, c=3)>

如果你想把它作为一个映射(类似字典),你可以访问 BoundArguments.arguments 属性:

>>> sig.bind(a, b, c).arguments
OrderedDict([('a', 10), ('b', 2), ('c', 3)])

甚至将其转换为普通字典:

>>> dict(sig.bind(a, b, c).arguments))
{'a': 10, 'b': 2, 'c': 3}

如果你想记录函数输入,你应该使用包装器:

import inspect

def log_args(func):
    def log_and_call(*args, **kwargs):
        sig = inspect.signature(func)
        bound_args = sig.bind(*args, **kwargs)
        bound_args.apply_defaults()
        loggable_args = bound_args.arguments

        print("Function name: " + func.__name__)
        for key, val in loggable_args.items():
            print(key + " = " + str(val))

        return func(*args, **kwargs)
    return log_and_call

@log_args
def do_sum(a, b, c=0):
    return a + b + c


x = do_sum(1,b=2)

这样可以很容易地记录每个函数调用,并防止样板代码。
请注意,我使用了 apply_defaults,因此如果没有提供不同的值,它将打印默认参数的值。
在示例中,我还给出了 b 的名称,尽管它不是具有默认值的参数,只是为了表明它有效。
您可以将打印替换为写入记录器或类似的东西。