Type Hints
Python 作為一個動態型別的語言,雖然享受著「開發速度快」及「容易上手」等美名,不過隨著專案越來越龐大,開發和 debug 的速度卻會因缺乏型別定義而下降,出現 bug 的機率也隨之上升。
不過 Python 自 3.5 推出後便導入 type hint,開始擁抱一些靜態型別的優點,舉例如下:
def greet(name: str) -> None:
print(f"Hello, my name is {name}.")
n: str = "Chris"
greet(n)由上面的例子我們可以發現:
定義 variables 以及 parameters 時使用
: {TYPE}定義 functions 時使用
-> {TYPE}。當
None用作 function 的 return type 時,意思是「沒有reurtnstatement,或 explicitlyreturn None,或 simplyreturn」
須注意的是,Python 的 type hints 是一種輔助用的功能,是給開發者和編輯器看的,不是給 Python Interpreter 看的,所以沒有 runtime checker,也不影響 Python 身為動態型別的本質。
換句話說,如果你用了 type hints,然後在程式碼裡面把一個 int assign 給型別為 str 的變數,還是可以執行(你只會在編輯器上看到五顏六色的警告)。
常用的 Types
Primitive Types
常用的 primitive types 包括:int、float、str、bool、None。
Non-Primitive Types
常用的 non-primitive types 包括:Tuple、List、Set 與 Dict。
List[X]:一個全部元素都是X型別的 list,比如List[int]Tuple[X]:一個全部元素都是X型別的 tuple,比如Tuple[int]Tuple[X, ...]:一個「第一個元素是X型別」,「其餘元素可以是任何型別」的 tuple,比如Tuple[int, ...]...在這裡的意思不是懶得寫,而是一個叫 "ellipsis" 的語法。
Set[X]:一個全部元素都是X型別的 set,比如Set[int]Dict[X, Y]:一個全部的 key 型別都是X,且全部的 value 型別都是Y的 dict
[!Info] 上述的 non-primitive types 皆必須先
from typing import {TYPE}才能使用,但在 Python 3.9 之後有 built-in types 可以取代之(就不用 import 了),詳見 此段。
Special Types
Union[X, Y]
型別可以是
X或Y,比如Union[int, float, None]。須先
from typing import Union,但在 Python 3.10 後可以用X | Y取代之。
Optional[X]
型別可以是
X或None,比如Optional[int]。須先
from typing import Optional,但在 Python 3.10 後可以用X | None取代之。
Callable[[Arg1Type, Arg2Type], ReturnType]
若一個 function 的接收兩個型別分別為 Arg1Type 與 Arg2Type 的參數,且 return 的型別為 ReturnType 的值,則該 function 的型別可以定義如上。
若想要定義一個「不限制參數的數量與型別」的 function,則可以寫:Callable[..., ReturnType]。
ClassVar[T]
定義 class variable 時可以使用它,T 的部分就是原本的資料型態,比如 ClassVar[int]。
After Python 3.8
Literal
Literal規範某變數或 function 的回傳值只能為某些特定值,舉例如下:
from typing import Literal
def open_helper(file: str, mode: Literal["r", "rb", "w", "wb"]) -> str:
...Final
Final定義某變數為常數,效果類似 JavaScript 中的 const,舉例如下:
from typing import Final
PI: Final[float] = 3.14159
PI = 0 # Error reported by type checker[!Note] 注意 現在還無法檢查到
+=等 Augmented Assignment,以上例而言,PI += 1是不會出現錯誤提示的。
After Python 3.9
在 Python 3.9 前,Tuple、List、Set、Dict 等 types 要從 typing module import,不過 3.9 後可以直接使用 built-in 的 tuple、list、set 與 dict 替代之,Tuple、List、Dict 等則變為 deprecated,詳情請見 官方文件。
Before 3.9:
from typing import Tuple, List, Dict, Set
a: Tuple[int] = (0, )
b: List[str] = ["a"]
c: Dict[str, int] = {"a": 0}
d: Set[int] = {1, 2, 3}Since 3.9:
a: tuple[int] = (0, )
b: list[str] = ["a"]
c: dict[str, int] = {"a": 0}
d: set[int] = {1, 2, 3}After Python 3.10
X | Y 取代 Union[X, Y]
X | Y 取代 Union[X, Y]X | None 取代 Optional[X]
X | None 取代 Optional[X]TypeAlias
TypeAlias可以把型別存成變數,舉例如下:
from typing import TypeAlias, Literal
MODE: TypeAlias = Literal["r", "rb", "w", "wb"]
def open_helper(file: str, mode: MODE) -> str:
...After Python 3.12
type Statement 取代 3.10 的 TypeAlias
type Statement 取代 3.10 的 TypeAlias定義一個名為 Point 的 type alias:
type Point = tuple[float, float]也可以搭配 generic 使用:
type Point[T] = tuple[T, T]參考資料
Last updated