Python函数参数的五种类型

以前项目需求,须要经过反射获取函数的参数,python中能够经过函数签名(signature)来实现。python

 

首先须要了解函数参数的类型,Python的参数类型一共有5种:POSITIONAL_OR_KEYWORD(定位或关键字)、VAR_POSITIONAL(定位)、VAR_KEYWORD(关键字)、KEYWORD_ONLY(仅有关键字)、POSITIONAL_ONLY(仅有定位)app

其中 POSITIONAL_OR_KEYWORD、VAR_POSITIONAL、VAR_KEYWORD、KEYWORD_ONLY 比较经常使用函数

参数类型为VAR_POSITIONAL时,即*args参数,只能经过位置传值,如orm

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

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

参数类型为VAR_KEYWORD,即 **kwargs参数,只能经过关键字传值,如it

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

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

参数的类型为POSITIONAL_OR_KEYWORD时,说明此参数前面没有VAR_POSITIONAL类型的参数,能够经过位置或关键字传值,如form

 

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

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

 

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

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

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

比较特别的是POSITIONAL_ONLY,只能经过位置传值的参数。Python并无明确的语法去定义一个只能经过位置传值的函数参数,可是在不少内置和扩展模块的函数会接受这种类型的参数。test

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

 

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)
相关文章
相关标签/搜索