Python作為一門動態語言,其變數的型別可以自由變化。這個特性提高了程式碼的開發效率,卻也增加了閱讀程式碼和維護程式碼的難度。
假設有一個變數is_request_finished
,從名字上來看,這個變數的值應該為True
或者False
,在寫程式碼的時候,最初也確實是這樣定義的。但是可能由於某些原因,在某一次賦值的時候,is_request_finished = ‘True’。此時,如果程式碼的單元測試不夠完善,那麼if is_request_finished
在 is_request_finished = True
和 is_request_finished = 'True'
的時候都成立,問題被隱藏了。但是當is_request_finished = 'False'
的時候,由於'False'
作為一個非空字串,就會使得if is_request_finished
依然成立,從而使程式的行為發現異常。
單個變數的型別異常也許還容易發現,但是如果變數是放在字典或者串列裡面,那就比較麻煩了。假設需要儲存一段個人資訊,於是建立了下麵這樣一個串列套字典的資料結構:
這種方式開發起來非常的快速而方便,但是其他人甚至是開發者自己在一段時間以後讀程式碼,都會有一種想抽死自己的衝動。因為根本不知道這個變數裡面儲存的是什麼東西。
針對以上問題,常見的解決辦法有三種。
Type Hints 與 Variable Annotations
在PEP 484中,引入了Type Hints,在PEP 526中引入了Variable Annotations。它使得Python 3.6及以後的Python 程式碼擁有了“宣告”變數型別的能力。這裡的“宣告”之所以會打引號,是因為這個宣告是給IDE和人看的。這個宣告對 Python 的直譯器無效。
Type Hints
PyCharm現在已經可以比較好地支援Type Hints了。例如下麵這一段程式碼:
模擬一段上傳檔案的函式,上傳成功以後傳回True。接收一個引數url
。在正常情況下,這個url
應該是一個字串。於是,使用Type Hints,程式碼可以變為:
如果直接執行,其執行效果如下圖所示:
現在假設傳遞一個不是字串的變數給upload
函式,此時PyCharm就會提示型別有問題,如下圖所示:
但提示歸提示,強行執行也是沒有問題的。這就說明Type Hints主要是給IDE和人用的,直譯器並不會關心型別正不正確。
如果修改這個函式的傳回值,讓它不傳回True
或者False
,PyCharm 也會發出警告:
Type Hints的官方檔案,可以參閱:typing — Support for type hints
Variable Annotations
對於Variable Annotations,如下圖所示,雖然目前PyCharm還不能很好地提示變數型別不對,但是人在讀程式碼的時候,還是會起到一定的幫助。
除了這種寫法外,Variable Annotations還支援把型別寫在註釋中,如下圖所示:
雖然PyCharm不能起到很好的提示作用,但是可以使用一個第三方庫mypy
來對程式碼做靜態檢查,其執行效果如下圖所示,可以發現賦值的型別與宣告的型別不一致(expression has type “str”, variable has type “bool”, 運算式的型別為“str”,變數的型別是“bool”)。
關於Variable Annotations的更多用法,可以參閱:Syntax for Variable Annotations
關於Mypy,可以參閱它的官方檔案。
docstring
在docstring來標註變數的型別,如下圖所示:
這種寫法可以用來提示一個函式,或者一個類它裡面的各個變數的情況。但是詳細程度需要看開發者有沒有耐心把這個註釋寫清楚。
Bean
這種方法來自與Java Bean的思想,它主要用來解決串列套字典,字典套字典,字典套串列,串列套串列這種深層的巢狀關係。
作者:Kingname
來源:http://kingname.info/2017/06/11/type-hints-in-python3/