Python 型別提示 Type Hints 介紹和基礎教學

Python 是動態強型別語言,宣告和賦值並不需要 var, let, const 之類的關鍵字,只要讓「名子」和「資料」綁定即可,依照變數所帶的資料就會自動決定這個變數的型別,傳入的參數也是。
    
def greeting(name):
    return "Hello " + name
    
name = 'world'
greeting(name)
    

這樣的設計很自由,然而隨著專案越來越大,很多時候我們不太容易判斷所有變數、函式的型別、格式。

Python 增強建議提案編號 484 (PEP 484)新增了 typing ,讓我們從 Python3.5 開始能夠將 Python 程式碼附上型別。
    
def greeting(name: str) -> str:
    return 'Hello ' + name
    
name: str = 'world'
print_hi(name)
    

在使用前我們先來看看 Type Hints 的優劣:

優點:
  • 在執行前就能夠發現大多數的型別錯誤
  • 使用 IDE 時獲得方便快速的提示
  • 方便理解程式碼
  • 可選的,並非使用了 Type Hints 就都一定要宣告型別
缺點:
  • 囉嗦、麻煩,需要多撰寫程式碼
  • 某些複雜的參數使用 Type Hints 後看起來很複雜難懂
  • 第三方套件並非都有使用 Type Hints ,無法知道套件相關程式碼的資料類型
總而言之,Type Hints 是 Python 官方提供給開發者的一個「新的註解方式」 ,方便開發者透過 Type Hints 了解程式碼、讓開發工具發出警告和建議來輔助開發者。

上面已經示範過在變數後面加上型別和定義函式的回傳值,下面這個範例是「傳入參數可以是任何型態,且函式沒有回傳值」,不過這個情況會使用到 Type Hints 的比較少見,因為很多人習慣省略:
    
def print_hi(name: any) -> None:
    print(f'Hi, {name}')
    

可以宣告的型別除了主要的型別外,還可以放 any, None, NoReturn(沒有回傳值或是拋出例外), Optional(可選), 自訂類別 (Class), 型別別名(TypeAlias)

NoReturn(沒有回傳值或是拋出例外):
沒有回傳值:
    
from typing import NoReturn

def stop() -> NoReturn:
    print('stop!')
    

拋出例外:
    
from typing import NoReturn

def stop() -> NoReturn:
    raise RuntimeError('stop!')
    


Optional(可選):
呼叫函式時可以不用 name 參數,預設值為 world
    
def print_hi(name: Optional[str] = 'world') -> None:
    print(f'Hi, {name}')
    

型別別名:
    
from typing import TypeAlias

res_type: TypeAlias = list[tuple[str, int]]
# res_type = list[tuple[str, int]] # 可省略 TypeAlias

res: res_type = [('a', 1), ('b', 2)]
    

在自訂類別中回傳當前類別:
如果不是使用字串會拋出這個錯誤: NameError: name 'Point' is not defined
因為此時 Point 還沒被定義,以下是正確的用法:
    
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other: 'Point') -> 'Point':
        self.x += other.x
        self.y += other.y
        return self
    


參考資料:
PEP 484 – Type Hints
PEP 3107 – Function Annotations
typing — Support for type hints
知呼 — 為什麼說 Python 是強類型語言?

留言