Python之簡單使用inspect.signature(fn).parameters判斷函式引數和預設值
參考官方文件:https://docs.python.org/zh-cn/3.7/library/inspect.html
inspect
inspect
模組提供了一些有用的函式幫助獲取物件的資訊,例如模組、類、方法、函式、回溯、幀物件以及程式碼物件。例如它可以幫助你檢查類的內容,獲取某個方法的原始碼,取得並格式化某個函式的引數列表,或者獲取你需要顯示的回溯的詳細資訊。
該模組提供了4種主要的功能:型別檢查、獲取原始碼、檢查類與函式、檢查直譯器的呼叫堆疊。
本章簡單介紹inspect.signature(fn).parameters獲取函式引數的引數名,引數的屬性,引數的預設值
示例
D:\learn-python3\學習指令碼\inspect檢查物件\use_inspect.py
# 匯入模組 import inspect def foo(a,b=1,*c,d,**kw): pass # 獲取函式引數返回一個有序字典 parms = inspect.signature(foo).parameters print(parms) # # 獲取引數名,引數屬性,引數預設值 for name,parm in parms.items(): print(name,parm.kind,parm.default)
關於函式的引數參考:https://www.cnblogs.com/minseo/p/14816422.html
以上例子,我們定義了一個測試函式,其中引數a,b是位置引數,b有預設值,c加了*號代表可變引數,d因為接在帶*號的引數c後,所以d為關鍵字引數,關鍵字引數需要使用引數名傳遞加等於的值傳遞值
遍歷郵箱字典,其中key即為引數名,parm為引數的屬性,使用kind輸出是什麼引數,比如位置引數,可變引數,關鍵字引數,字典引數,defalu為預設值
輸出如下
a POSITIONAL_OR_KEYWORD <class 'inspect._empty'> b POSITIONAL_OR_KEYWORD 1 c VAR_POSITIONAL <class 'inspect._empty'> d KEYWORD_ONLY <class 'inspect._empty'> kw VAR_KEYWORD <class 'inspect._empty'>
很明顯a,b為位置引數,c為可變引數,d為關鍵字引數,kw為字典引數
官方的引數屬性列表為
名稱 |
含義 |
---|---|
POSITIONAL_ONLY |
Value must be supplied as a positional argument. Python has no explicit syntax for defining positional-only parameters, but many built-in and extension module functions (especially those that accept only one or two parameters) accept them. |
POSITIONAL_OR_KEYWORD |
Value may be supplied as either a keyword or positional argument (this is the standard binding behaviour for functions implemented in Python.) |
VAR_POSITIONAL |
A tuple of positional arguments that aren't bound to any other parameter. This corresponds to a |
KEYWORD_ONLY |
Value must be supplied as a keyword argument. Keyword only parameters are those which appear after a |
VAR_KEYWORD |
A dict of keyword arguments that aren't bound to any other parameter. This corresponds to a |
根據以上我們可以寫出以下幾個函式判斷函式的引數
# 定義函式傳遞引數為函式,然後取出引數進行判斷 # 如果函式引數包含關鍵字引數並且關鍵字引數值為空則返回關鍵字引數的元組 def get_required_kw_args(fn): args = [] params = inspect.signature(fn).parameters for name, param in params.items(): if param.kind == inspect.Parameter.KEYWORD_ONLY and param.default == inspect.Parameter.empty: args.append(name) return tuple(args) # 如果有關鍵字引數則取出返回元組 def get_named_kw_args(fn): args = [] params = inspect.signature(fn).parameters for name, param in params.items(): if param.kind == inspect.Parameter.KEYWORD_ONLY: args.append(name) return tuple(args) # 判斷函式是否有關鍵字引數,如果有則返回True def has_named_kw_args(fn): params = inspect.signature(fn).parameters for name, param in params.items(): if param.kind == inspect.Parameter.KEYWORD_ONLY: return True # 判斷函式是否有字典引數,如果有則返回True def has_var_kw_arg(fn): params = inspect.signature(fn).parameters for name, param in params.items(): if param.kind == inspect.Parameter.VAR_KEYWORD: return True # 判斷函式的引數有沒有request,如果有request引數則把found賦值為True並結束本次迴圈繼續判斷其他引數 # 如果其他引數不是可變引數,也不是關鍵字引數,也不是字典引數則丟擲錯誤 # 例如響應函式index(request)只有一個引數request所以在執行第一個if以後就沒有引數迴圈了,退出整個迴圈返回found的值為True def has_request_arg(fn): sig = inspect.signature(fn) params = sig.parameters found = False for name, param in params.items(): if name == 'request': found = True continue if found and (param.kind != inspect.Parameter.VAR_POSITIONAL and param.kind != inspect.Parameter.KEYWORD_ONLY and param.kind != inspect.Parameter.VAR_KEYWORD): raise ValueError('request parameter must be the last named parameter in function: %s%s' % (fn.__name__, str(sig))) return found print(get_required_kw_args(foo),get_named_kw_args(foo),has_named_kw_args(foo),has_var_kw_arg(foo),has_request_arg(foo)) # ('d',) ('d',) True True False def index(request): pass print(has_request_arg(index)) # True
輸出如下
('d',) ('d',) True True False True
解析
get_required_kw_args(foo) # 有關鍵字引數d,並且預設值為空輸出引數名組成的元組 get_named_kw_args(foo)# 有關鍵字引數d,輸出引數名組成的元素 has_named_kw_args(foo)# 判斷有沒有關鍵字引數,有d輸出為True has_var_kw_arg(foo) # 判斷有沒有字典引數,有kw輸出為True has_request_arg(foo)# 判斷引數有沒有名字為request的,沒有輸出False has_request_arg(index)# 函式index有名為default的引數,返回True