第 25 課 · 進階 · 19 分鐘

Python 型別提示

讓讀者和工具一眼看出資料的形狀。

型別提示函式註解list[int]可選回傳值

新來的店員看著訂單字典,猜「qty」是什麼意思。型別標註在程式碼跑起來之前就說明它是整數。可 Python 在執行時真的會管嗎?

型別提示是可選的註解,用來說明函式接收和回傳什麼樣的值。Python 執行時不會強制執行這些提示,但編輯器、檢查工具和同事可以藉此在執行前發現錯誤。 你還會描述回呼、類 JSON 記錄,以及輸入與輸出型別之間的關係。

給函式加註解

參數後面的冒號寫出預期型別,箭頭寫出回傳型別。提示會儲存在 __annotations__ 中,但不會轉換值。傳入非字串仍然會執行,直到程式碼本身出錯。

def greet(name: str) -> str:
    return f"Hello, {name}"
print(greet("Ada"))

參數與回傳型別

描述集合

list[int] 表示每個元素都是 int。現代 Python 支援內建泛型,讀起來也很直接。提示描述的是介面,不會在函式呼叫時逐個檢查元素。

def total(values: list[int]) -> int:
    return sum(values)
print(total([1, 2, 3]))

帶型別的列表

說明值可能不存在

鍵不存在時,dict.get 回傳 None,所以回傳型別也應包含 None。聯合型別寫法 float | None 直接表達這種可能。呼叫方可以先處理缺失情況,再做算術。

def find_price(prices: dict[str, float], item: str) -> float | None:
    return prices.get(item)
print(find_price({"tea": 3.5}, "tea"))
print(find_price({"tea": 3.5}, "coffee"))

可能有值,也可能是 None

Callable 與 Iterable 描述行為

型別提示不只描述內建型別,也能描述函式接受什麼。Callable[[int], int] 表示參數是從 int 到 int 的函式;Iterable[int] 接受列表、生成器和其他流。提示幫助編輯器,不改變執行時行為。

from collections.abc import Callable, Iterable

def apply_all(values: Iterable[int], operation: Callable[[int], int]) -> list[int]:
    return [operation(value) for value in values]

print(apply_all([1, 2, 3], lambda n: n * 2))

連回呼一起註解

TypedDict 描述記錄形狀

TypedDict 給字典的鍵和值型別起名字,適合 JSON 邊界。執行時它仍然是普通 dict,不會自動檢查鍵或型別。解碼後仍要單獨驗證資料,再信任它。

from typing import TypedDict

class Order(TypedDict):
    drink: str
    price: float
    quantity: int

order: Order = {"drink": "latte", "price": 4.5, "quantity": 2}
print(order["drink"], order["price"] * order["quantity"])

給鍵起名,不改變執行時

TypeVar 保持輸入輸出關係

TypeVar 表示同一個型別在函式中流動。first(list[int]) 回傳 int | None,first(list[str]) 回傳 str | None。沒有型別變數,最多只能說回傳 object,呼叫方會丟失有用資訊。

from typing import TypeVar
T = TypeVar("T")

def first(items: list[T]) -> T | None:
    return items[0] if items else None

print(first([1, 2, 3]))
print(first(["latte"]))
print(first([]))

把元素型別帶到回傳值

本課要點

  • 參數提示寫在冒號後,回傳提示寫在 -> 後。
  • list[int] 和 dict[str, float] 描述集合裡的內容。
  • float | None 表示值可能缺失。
  • 型別提示是文件和工具輸入,不是執行時強制檢查。
  • 提示描述介面;TypedDict 和 TypeVar 補充形狀與關係,不做執行時檢查。

常見錯誤

  • 以為違反型別提示時 Python 會自動拋出 TypeError。
  • 只在註解裡寫 list[int],卻沒有寫進函式籤名。
  • 尋找可能失敗時,回傳型別忘記包含 None。
  • 以為違反註解本身就會拋出 TypeError。
輪到你

給 double(n: int) -> int 加註解並列印 double(4),再給一個回傳 str | None 的函式加註解。

動手試試

改改變數、先預測輸出,再執行程式碼。第一次點擊「執行程式碼」時會下載 Python 執行時,可能需要幾秒鐘。

瀏覽器內 Python本機執行 · 無需帳號
首次執行會從 CDN 下載 Pyodide。修改後點擊「執行程式碼」。

練習本課

12 道題,作答後立即看到解釋。

查看 12 道題答案開始練習
← assert 測試生成器 →