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)
相關文章
相關標籤/搜索