新來的店員看著訂單字典,猜「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 執行時,可能需要幾秒鐘。
練習本課
12 道題,作答後立即看到解釋。