參考資料:
https://blog.csdn.net/weixin_40908748/article/details/106252884
https://www.python.org/dev/peps/pep-0484/
https://www.jetbrains.com/help/pycharm/stubs.html
寫這篇文章的原因是我在網上下載的項目中看到了.pyi文件,但是尋找了很多資料才對這些個概念(存根文件、類型檢查)有了一個直觀的印象。這篇隨筆的目的是用最短的篇幅讓你理解這些概念!
首先我介紹幾個論斷:
1. PEP484
首先PEP是Python社區使用的規范化文檔(就好像IETF用的rtf),PEP484這個文檔是對type hint作規范化的文檔!它規范化了type hint所需的語法用法...比如如果你關心stub存根文件是怎么做規范化的,你可以看參考資料2。
2.type checker
PEP484只是一個規范化的文檔,沒有給出具體的hint軟件。事實上有一個內置模塊叫typing,但它是讓你用規范的語法寫type hint的。不是一個類型檢查器!!!
問:有哪些類型檢查器可用?答:Pycharm內置有type checker,並且可用,明確支持stub file。mypy這個軟件明確支持stub。其他的hinter,pyhinter等...我測試了一下,在vscode中效果不理想。
3.來看看,一個最簡單的type hint,一個最簡單的stub file長什么樣
一個最簡單的帶annotation(type hint)的函數定義:
def greeting(name: str) -> str: return "Hello" + name
一個最簡單的stub file:
def greeting(name: str) -> str: ...
4.后綴為.pyi的stub存根文件的作用:
當沒有存根文件,同時在函數定義的時候不加annotation的情況:
可見,由於python沒有內置靜態類型檢查,只有運行時的動態檢查。Pycharm給這個在運行時會出錯的文件打了小對勾。
但是,當我們在同一個文件夾下寫一個stub file之后呢?
有了stub file的指引,有了Pycharm內置的type checker做靜態檢查驅動。在代碼沒有運行的時候就檢查出來了類型錯誤!!這在維護大型的項目的時候是非常有用的。
看了上面這幾個論斷,你是不是對相關的概念有了一個初步的理解?下面我們自己動手做一個實驗,目的是在一個文件夾中寫module並定義函數,在另一個文件夾中統一存放存根文件(因為方便管理呀,並且能夠多次使用實現復用!)而且我們已經知道了,type checker這個活不是必須的,可以由mypy,Pycharm來干,那么我們想找到指導當然要尋求這些工具的指導。比如:Pycharm的stub說明。https://www.jetbrains.com/help/pycharm/stubs.html#create-stub-external,廢話不多說,動手做一做。
第一步:
生成代碼文件和存根文件,其中存根文件放到一個統一的文件夾中統一存放。
第二步:
按照Pycharm文檔中的指引,將存根文件的目錄添加到PATH中,一定要注意文件名要對應上。(在IDE中可以方便的配置,當真正工程上應用的話可能就要手動添加PATH了,但要注意:hints是給人看的,類型檢查也是給人警告的,不能脫離應用)
Reuse stubs
You can make your stubs accessible for your other PyCharm projects.
-
Click the Project Interpreter selector in the Status Bar and select
-
In the Project Interpreter dialog, click
and select
-
In the Interpreter paths dialog, click
to add the new path record:
-
Inspect your project: the directory with the stub files is now marked as a library root.
Any time you will use this project interpreter to work with other projects, this stub library will be accessible through the path you have just added.
第三步:
看一下結果,發現兩個module文件都找到了對應的存根。其中在最左邊出現了 * ,點擊的話可以在實現以及存根中跳轉。