Python 型別提示:撰寫更安全、清晰的程式碼

Backend2026-09-13TryQuickToolBox

你可能遇過某個 Python 函式會根據輸入回傳不同型別,或是某個變數中途改變型別。這些模糊地帶會導致執行時錯誤,而這些錯誤其實可以提前被發現。Python 型別提示能解決這個問題,它讓你標註預期的型別,使程式碼具備自我說明性,並讓靜態分析工具在執行前就捕捉到錯誤。

在本文中,我們將探討如何有效使用 Python 型別提示,從基礎標註到進階模式,以及它們如何協助你寫出更安全、更清晰的程式碼。

什麼是 Python 型別提示?

型別提示(也稱為型別標註)是 Python 3.5 引入的語法(PEP 484),允許你指定變數、函式參數與回傳值的預期型別。它們不會在執行時強制檢查,但會被 mypy、pyright 等靜態型別檢查器及 IDE 用來偵測型別相關的錯誤。

例如:

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

這裡的 name: str 表示 name 應該是字串,而 -> str 表示函式回傳字串。

為什麼要使用型別提示?

基礎型別標註

你可以標註變數、函式參數與回傳型別。

變數

age: int = 30
name: str = "Alice"

函式

def add(a: int, b: int) -> int:
    return a + b

集合

對於串列、字典等,請使用 typing 模組(或在 Python 3.9+ 使用內建泛型):

from typing import List, Dict

def process(items: List[str]) -> Dict[str, int]:
    return {item: len(item) for item in items}

在 Python 3.9+ 中,你可以直接使用 list[str] 和 dict[str, int]。

進階型別提示

隨著程式碼增長,你會遇到更複雜的情境。以下是一些進階功能。

Optional 與 Union

Optional[T] 是 Union[T, None] 的簡寫,表示值可以是 T 型別或 None。

from typing import Optional

def find_user(user_id: int) -> Optional[str]:
    # 回傳使用者名稱,若找不到則回傳 None
    ...

在 Python 3.10+ 中,你可以使用 | 運算子:str | None。

Callable

用於將函式作為參數:

from typing import Callable

def apply_func(func: Callable[[int], int], value: int) -> int:
    return func(value)

泛型

使用型別變數建立可重複使用的元件:

from typing import TypeVar, List

T = TypeVar('T')

def first(items: List[T]) -> T:
    return items[0]

TypedDict

用於具有固定鍵集合與值型別的字典:

from typing import TypedDict

class User(TypedDict):
    name: str
    age: int

def greet(user: User) -> str:
    return f"Hello, {user['name']}"

使用靜態型別檢查器

型別提示只有在檢查時才有用。常見工具包括 mypy、pyright 和 pyre。讓我們看看如何使用 mypy。

  1. 安裝 mypy:pip install mypy
  2. 對你的程式碼執行:mypy your_script.py
  3. 修正回報的錯誤。

例如,給定以下程式碼:

def add(a: int, b: int) -> int:
    return a + b

add("1", "2")

mypy 會回報:error: Argument 1 to "add" has incompatible type "str"; expected "int"。

你可以透過 mypy.ini 或 pyproject.toml 檔案設定 mypy 以執行更嚴格的檢查。

型別提示最佳實踐

常見陷阱與避免方法

型別提示實戰:一個小範例

考慮一個處理數字列表並回傳平均值的函式。沒有型別提示時,預期的型別並不清楚。

def average(numbers):
    return sum(numbers) / len(numbers)

加上型別提示後:

from typing import List

def average(numbers: List[float]) -> float:
    return sum(numbers) / len(numbers)

現在,如果有人傳入字串列表,mypy 會標記出來。

將型別提示整合到你的工作流程

要充分發揮型別提示的效益,請將它們整合到開發流程中:

  1. 逐步為現有程式碼庫加入型別提示。
  2. 設定 IDE 顯示型別錯誤。
  3. 在 CI 流程中加入型別檢查步驟。
  4. 使用 pre-commit 鉤子在提交前執行 mypy。

例如,一個簡單的 GitHub Actions 工作流程步驟:

- name: Type check
  run: mypy .

常見問題

型別提示會影響執行效能嗎?

不會,型別提示在執行時會被忽略。它們儲存在 __annotations__ 中,但不會影響執行速度。

我可以在較舊的 Python 版本中使用型別提示嗎?

型別提示於 Python 3.5 引入。對於更舊的版本,你可以使用基於註解的標註(例如 # type: int),但建議升級到受支援的 Python 版本。

型別提示中 List 和 list 有什麼區別?

typing 中的 List 用於 Python 3.5-3.8。在 Python 3.9+ 中,你可以直接使用內建的 list。兩者在型別檢查上是等效的。

準備好提升你的程式碼品質了嗎?今天就從為一個函式加上型別提示開始,並執行 mypy 來看看好處。如需更多開發者工具,請查看我們的 JSON Formatter,輕鬆美化並驗證你的 JSON 資料。