首页 > 代码库 > 动态获取函数的参数

动态获取函数的参数

之前项目需求,需要动态的获取函数的参数,查阅一些资料后,发现可以通过函数签名(signature)来实现,记录下做个备忘。

 

首先需要了解函数参数的类型,目前常用的参数类型主要有4种:POSITIONAL_OR_KEYWORD、VAR_POSITIONAL、VAR_KEYWORD、KEYWORD_ONLY

参数类型为VAR_POSITIONAL时,只能通过位置传值,如

def say_hello(*args):
    print(hello {0}.format(args))

# 通过位置传值
say_hello(jack, tom)

参数类型为VAR_KEYWORD,只能通过关键字传值,如

def func_b(**kwargs):
    print(kwargs)

# 通过关键字传值
func_b(a=1, b=2)

参数的类型为POSITIONAL_OR_KEYWORD时,说明此参数前面没有VAR_POSITIONAL类型的参数,可以通过位置或关键字传值,如

def say_hello(name):
    print(hello {0}.format(name))

# 通过位置传值
say_hello(jack)
# 通过关键字传值
say_hello(name=tom)

参数类型为KEYWORD_ONLY时,说明此参数前面存在VAR_POSITIONAL类型的参数,只能通过关键字传值,如

def func_b(*args, a, b):
    print(args, a, b)

# 只能通过关键字传值
func_b(test, a=1, b=2)

 

实际获取函数参数时,需要用到inspect模块,通过这个模块的signature方法获取函数签名。

import inspect


def func_a(arg_a, *args, arg_b=hello, **kwargs):
    print(arg_a, arg_b, args, kwargs)


if __name__ == __main__:

    # 获取函数签名
    func_signature = inspect.signature(func_a)
    func_args = []
    # 获取函数所有参数
    for k, v in func_signature.parameters.items():
        # 获取函数参数后,需要判断参数类型
        # 当kind为 POSITIONAL_OR_KEYWORD,说明在这个参数之前没有任何类似*args的参数,那这个函数可以通过参数位置或者参数关键字进行调用
        # 这两种参数要另外做判断
        if str(v.kind) in (POSITIONAL_OR_KEYWORD, KEYWORD_ONLY):
            # 通过v.default可以获取到参数的默认值
            # 如果参数没有默认值,则default的值为:class inspect_empty
            # 所以通过v.default的__name__ 来判断是不是_empty 如果是_empty代表没有默认值
            # 同时,因为类本身是type类的实例,所以使用isinstance判断是不是type类的实例
            if isinstance(v.default, type) and v.default.__name__ == _empty:
                func_args.append({k: None})
            else:
                func_args.append({k: v.default})
        # 当kind为 VAR_POSITIONAL时,说明参数是类似*args
        elif str(v.kind) == VAR_POSITIONAL:
            args_list = []
            func_args.append(args_list)
        # 当kind为 VAR_KEYWORD时,说明参数是类似**kwargs
        elif str(v.kind) == VAR_KEYWORD:
            args_dict = {}
            func_args.append(args_dict)

    print(func_args)

 

动态获取函数的参数