函數定義的弊端:python
python是動態語言,變量隨時能夠被賦值,且能賦值爲不一樣的類型;程序員
python不是靜態編譯語言,變量類型是在運行器決定的;ide
動態語言很靈活,可是這種特性也是弊端;函數
def add(x, y): return x + y print(add(4, 5)) print(add('hello', 'world')) add(4, 'hello')#
難發現:因爲不作任何類型檢查,直到運行期間問題才顯現出來,或者線上運行時才能暴露出問題;
工具
難使用:函數的使用者看到函數的時候,並不知道你的函數的設計,並不知道應該傳入什麼類型的數據;ui
如何解決這種動態語言定義的弊端呢?
spa
增長文檔Documentation String設計
這只是一個慣例,不是強制標準,不能要求程序員必定爲函數提供說明文檔;對象
函數定義更新了,文檔未必同步更新;文檔
def add(x, y): ''' :param x: int :param y: int :return: int ''' return x + y print(help(add))
那有沒有別的方法呢?
函數註解Function Annotations
def add(x: int, y: int) -> int: ''' :param x: int :param y: int :return: int ''' return x + y print(help(add)) print(add('hello', 'world')) ###思考一下這裏會報錯嗎?
Python 3.5引入
對函數的參數進行類型註解;
對函數的返回值進行類型註解;
只對函數參數作一個輔助的說明,並不對函數參數進行類型檢查;
提供給第三方工具,作代碼分析,發現隱藏的bug;
函數註解的信息,保存在__annotations__屬性中
add.__annotations__
{'y': <class 'int'>, 'x': <class 'int'>, 'return': <class 'int'>}
業務應用
函數參數類型檢查
思路:
函數參數的檢查,必定是在函數外;
函數應該做爲參數,傳入到檢查函數中;
檢查函數拿到函數傳入的實際參數,與形參聲明對比;
__annotations__屬性是一個字典,其中包括返回值類型的聲明。假設要作位置參數的判斷,沒法和
字典中的聲明對應。
使用inspect模塊
inspect模塊:
提供獲取對象信息的函數,能夠檢查函數和類、類型檢查。
signature(callable),獲取簽名(函數簽名包括了一個函數的信息,包括函數名,參數類型,它所在的類和名稱空間及其餘信息)
import inspect def add(x: int, y: int, *args, **kwargs) -> int: return x + y sig = inspect.signature(add) print(sig) print("param : ", sig.parameters)#OrderedDict print("return :", sig.return_annotation) print(sig.parameters['y']) print(sig.parameters['x'].annotation) print(sig.parameters['args']) print(sig.parameters['args'].annotation) print(sig.parameters['kwargs']) print(sig.parameters['kwargs'].annotation)
inspect.isfunction(add), 是不是函數;
inspect.ismethod(add), 是不是類的方法
inspect.isgenerator(add), 是不是生成器對象;
inspect.isgeneratorfunction(add), 是不是生成器函數;
inspect.isclass(add), 是不是類;
inspect.ismodule(inspect), 是不是模塊
isclass.isbuiltin(print), 是不是內建對象
還有不少is函數,須要的時候查閱inspect模塊幫助;
parameter對象
保存在元組中,是隻讀的;
name, 參數的名字;
annotation, 參數的註解,可能沒有定義;
default, 參數的缺省值,可能沒有定義;
empty,特殊的類,用來標記default屬性或者註釋annotation屬性的空值;
kind,實參如何綁定到形參,就是形參的類型
POSITIONAL_ONLY ,值必須是位置參數提供
POSITIONAL_OR_KEYWORD, 值能夠做爲關鍵字或者位置參數提供;
VAR_POSITIONAL, 可變位置參數,對應*args;
KEYWORD_ONLY, keyword_only參數,對應*或者*args以後出現的非可變關鍵字參數;
VAR_KEYWORD, 可變關鍵字參數,對應**kwargs