Python 型別檢查

雨神姥爺發表於2017-01-20

眾所周知, Python 是一門強型別、動態型別檢查的語言。所謂動態型別,是指在定義變數時,我們無需指定變數的型別,Python 直譯器會在執行時自動檢查。與靜態型別語言(如 C 語言)相比,這不僅僅是少寫了幾個型別宣告字元:

#include <stdlib.h>
#include <stdio.h>

#define BUFF 100

char* greeting(char* name){
  char* msg = (char *) malloc(sizeof(char) * BUFF);
    sprintf(msg, "Hello, %s!", name);
    return msg;
}

int main(){
    printf("Greeting: <%s>\n", greeting("C99"));
    return 0;
}複製程式碼
def greeting(name):
    return "Hello, {}!".format(name)
def main():
    print("Greeting: <%s>" % greeting("Python35"))
if __name__ == '__main__':
    main()複製程式碼

動態型別從一定程度上將我們的思維從對計算機的工作模擬中解放出來,可以將更多精力集中在需要解決的問題上:就像上面的例子,我們不需要費心思考慮greeting函式所接受的引數是什麼型別、返回值是什麼型別,而只需要考慮greeting函式需要實現的功能即可。

當然並不是說動態型別一定優於靜態型別,上面的例子用 C 語言和 Python 相比也有失公允,如果換成 Go 語言:

package main

import "fmt"

func greeting(name string) string {
    return fmt.Sprintf("Hello, %s", name)
}
func main() {
    fmt.Printf("Greeting: <%s>", greeting("Go"))
}複製程式碼

靜態型別的優勢(從某種程度上說也是缺點)在於定義方法時制定一種強制性的協議(介面),只有遵循協議才能正確地使用。這對多人合作、開發第三方庫、快速定位 BUG 等是很有幫助的。靜態型別還有一大優勢是可以讓 IDE 幫助提示介面用法和型別檢查,進一步提高效率。既然有這麼多優勢,那 Python 要不要也學習一個?實際上 Python 3.5 中的 PEP 484 和 Python 3.6 的 PEP 526 分別加入了型別提示(Type Hints)的語法,其中 PEP 484 主要關於函式、方法、類的引數和返回值的型別宣告語法,而 PEP 526新增了對變數型別的宣告:

def greeting(name: str) -> str:
    return "Hello, {}!".format(name)複製程式碼

Mypy

Mypy 是官方推薦一個靜態型別檢查工具:

python3 -m pip install mypy複製程式碼

可以用 mypy 命令直接檢查 Python 程式:

mypy greeting.py複製程式碼

為了方便使用,可以將其應用到 IDE 中,以 Atom 為例,可以安裝外掛linter-mypy

python3 -m pip install typed-ast
apm install linter
apm install linter-mypy複製程式碼

Python 型別檢查
Atom mypy linter.jpg

Mypy 支援的常用型別如下表所示(來自官方文件):

Python 型別檢查
builtin types.png

其中List/Dict/Iterable/Sequence/Any來自標準庫 typing。這裡的 SequenceIterable分別對應collections.abc.Sequencecollections.abc.Iterable,簡單來區分Sequence是可以通過數字下標索引的,而Iterable可以代表生成器:

Python 型別檢查
Sequence.jpg

Python 2.x

新增了型別註釋的程式碼可以直接通過 Python 3.5 直譯器執行,但是對於 Python 2.x 則是完全不相容的。如果要在 Python 2.x 中使用,首先需要安裝 typing

pip install typing複製程式碼

然後可以用單行註釋的形式強行新增:

def send_email(address,     # type: Union[str, List[str]]
               sender,      # type: str
               cc,          # type: Optional[List[str]]
               bcc,         # type: Optional[List[str]]
               subject='',
               body=None    # type: List[str]
               ):
    # type: (...) -> bool
    """Send an email message.  Return True if successful."""
    pass複製程式碼

總結

Python 3.5+ 從語法上支援靜態型別提示,在不影響正常使用習慣的情況下為我們提供靜態型別檢查的功能,雖說不能與真正的靜態型別語言相比,但也保證了更大的靈活性,這也符合 Python 的一貫的設計思想:“It's a tool, not a rule.”


原文連結:http://blog.rainy.im/2017/01/20/python-type-hints/

相關文章