Python函數參數的五種類型


之前項目需求,需要通過反射獲取函數的參數,python中可以通過函數簽名(signature)來實現。

 

首先需要了解函數參數的類型,Python的參數類型一共有5種:POSITIONAL_OR_KEYWORD、VAR_POSITIONAL、VAR_KEYWORD、KEYWORD_ONLY、POSITIONAL_ONLY

其中 POSITIONAL_OR_KEYWORD、VAR_POSITIONAL、VAR_KEYWORD、KEYWORD_ONLY 比較常用

參數類型為VAR_POSITIONAL時,即*args參數,只能通過位置傳值,如

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

# 通過位置傳值
say_hello('jack', 'tom')

參數類型為VAR_KEYWORD,即 **kwargs參數,只能通過關鍵字傳值,如

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)

比較特別的是POSITIONAL_ONLY,只能通過位置傳值的參數。Python並沒有明確的語法去定義一個只能通過位置傳值的函數參數,但是在很多內置和擴展模塊的函數會接受這種類型的參數。

實際獲取函數參數時,需要用到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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM