typing --- 支援型別提示

在 3.5 版被加入.

原始碼:Lib/typing.py

備註

Python runtime 不強制要求函式與變數的型別註釋。他們可以被第三方工具使用,如:型別檢查器、IDE、linter 等。


此模組提供 runtime 型別提示支援。

動腦筋思考下面的函式:

def surface_area_of_cube(edge_length: float) -> str:
    return f"The surface area of the cube is {6 * edge_length ** 2}."

函式 surface_area_of_cube 需要一個引數且預期是一個 float 的實例,如 edge_length: float 所指出的型別提示。這個函式預期會回傳一個 str 的實例,如 -> str 所指出的提示。

儘管型別提示可以是簡單類別,像是 floatstr,他們也可以變得更為複雜。模組 typing 提供一組更高階的型別提示詞彙。

新功能會頻繁的新增至 typing 模組中。typing_extensions 套件為這些新功能提供了 backport(向後移植的)版本,提供給舊版本的 Python 使用。

也參考

型別小抄 (Typing cheat sheet)

型別提示的快速預覽(發布於 mypy 的文件中)

mypy 文件的 型別系統參考資料 (Type System Reference) 章節

Python 的加註型別系統是基於 PEPs 進行標準化,所以這個參照 (reference) 應該在多數 Python 型別檢查器中廣為使用。(某些部分依然是特定給 mypy 使用。)

Python 的靜態型別 (Static Typing)

由社群編寫的跨平台型別檢查器文件 (type-checker-agnostic) 詳細描述加註型別系統的功能、實用的加註型別衍伸工具、以及加註型別的最佳實踐 (best practice)。

Python 型別系統的技術規範

關於 Python 型別系統標準的 (canonical)、最新的技術規範可以在Python 型別系統的技術規範找到。

型別別名

一個型別別名被定義來使用 type 陳述式,其建立了 TypeAliasType 的實例。在這個範例中,Vectorlist[float] 會被當作和靜態型別檢查器一樣同等對待:

type Vector = list[float]

def scale(scalar: float, vector: Vector) -> Vector:
    return [scalar * num for num in vector]

# passes type checking; a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])

型別別名對於簡化複雜的型別簽名 (complex type signature) 非常好用。舉例來說:

from collections.abc import Sequence

type ConnectionOptions = dict[str, str]
type Address = tuple[str, int]
type Server = tuple[Address, ConnectionOptions]

def broadcast_message(message: str, servers: Sequence[Server]) -> None:
    ...

# The static type checker will treat the previous type signature as
# being exactly equivalent to this one.
def broadcast_message(
    message: str,
    servers: Sequence[tuple[tuple[str, int], dict[str, str]]]
) -> None:
    ...

type 陳述式是 Python 3.12 的新功能。為了向後相容性,型別別名可以透過簡單的賦值來建立:

Vector = list[float]

或是用 TypeAlias 標記,讓它明確的表示這是一個型別別名,而非一般的變數賦值:

from typing import TypeAlias

Vector: TypeAlias = list[float]

NewType

使用 NewType 輔助工具 (helper) 建立獨特型別:

from typing import NewType

UserId = NewType('UserId', int)
some_id = UserId(524313)

若它是原本型別的子類別,靜態型別檢查器會將其視為一個新的型別。這對於幫助擷取邏輯性錯誤非常有用:

def get_user_name(user_id: UserId) -> str:
    ...

# passes type checking
user_a = get_user_name(UserId(42351