2.1 Type Hints 基礎
2.1 Type Hints 基礎
Python 3.5 引入了型別提示(Type Hints),讓你可以為變數和函式添加型別註解。型別提示不會影響執行,但能大幅提升程式碼的可讀性和 IDE 的智慧提示功能。
為什麼需要型別提示?
沒有型別提示的程式碼
1def process(data):
2 return data.strip()
3
4result = process(input_value) # data 是什麼型別?strip() 能用嗎?有型別提示的程式碼
1def process(data: str) -> str:
2 return data.strip()
3
4result = process(input_value) # 清楚知道需要字串,返回字串基本語法
變數型別註解
1# 基本型別
2name: str = "Python"
3count: int = 42
4ratio: float = 3.14
5is_valid: bool = True
6
7# 可以不賦值(用於宣告)
8message: str # 稍後賦值函式型別註解
1def greet(name: str) -> str:
2 return f"Hello, {name}!"
3
4def add(a: int, b: int) -> int:
5 return a + b
6
7def print_message(msg: str) -> None:
8 print(msg) # 沒有返回值用 None實際範例:Hook 系統
來自 .claude/lib/git_utils.py 的範例:
1def run_git_command(
2 args: list[str],
3 cwd: Optional[str] = None,
4 timeout: int = 10
5) -> tuple[bool, str]:
6 """
7 執行 git 命令並返回結果
8
9 Args:
10 args: git 命令參數列表(不含 'git')
11 cwd: 執行目錄,預設為當前目錄
12 timeout: 命令超時時間(秒)
13
14 Returns:
15 tuple[bool, str]: (是否成功, 輸出內容或錯誤訊息)
16 """
17 try:
18 result = subprocess.run(
19 ["git"] + args,
20 cwd=cwd,
21 capture_output=True,
22 text=True,
23 timeout=timeout
24 )
25 if result.returncode == 0:
26 return True, result.stdout.strip()
27 else:
28 return False, result.stderr.strip()
29 except subprocess.TimeoutExpired:
30 return False, f"Command timed out after {timeout}s"分析這個函式的型別提示:
| 參數 | 型別 | 說明 |
|---|---|---|
args | list[str] | 字串列表 |
cwd | Optional[str] | 可選字串,可以是 None |
timeout | int | 整數,有預設值 |
| 返回值 | tuple[bool, str] | 布林和字串組成的元組 |
容器型別
列表(List)
1from typing import List # Python 3.9 前需要
2
3# Python 3.9+
4def process_names(names: list[str]) -> list[str]:
5 return [name.upper() for name in names]
6
7# Python 3.8 及之前
8def process_names(names: List[str]) -> List[str]:
9 return [name.upper() for name in names]字典(Dict)
1from typing import Dict
2
3# Python 3.9+
4def get_config() -> dict[str, int]:
5 return {"timeout": 10, "retries": 3}
6
7# Python 3.8 及之前
8def get_config() -> Dict[str, int]:
9 return {"timeout": 10, "retries": 3}集合(Set)
1# Python 3.9+
2def get_unique_items(items: list[str]) -> set[str]:
3 return set(items)元組(Tuple)
1# 固定長度和型別
2def get_position() -> tuple[int, int]:
3 return (10, 20)
4
5# 可變長度(同質)
6def get_values() -> tuple[int, ...]:
7 return (1, 2, 3, 4, 5)實際應用:Hook 輸出建立
來自 .claude/lib/hook_io.py:
1def create_pretooluse_output(
2 decision: str,
3 reason: str,
4 user_prompt: Optional[str] = None,
5 system_message: Optional[str] = None,
6 suppress_output: bool = False
7) -> dict:
8 """
9 建立 PreToolUse Hook 輸出格式
10
11 Args:
12 decision: 決策結果 ("allow" | "deny" | "ask")
13 reason: 決策原因說明
14 user_prompt: 詢問用戶的訊息
15 system_message: 系統訊息
16 suppress_output: 是否抑制輸出
17 """
18 output: dict[str, Any] = {
19 "hookSpecificOutput": {
20 "hookEventName": "PreToolUse",
21 "permissionDecision": decision,
22 "permissionDecisionReason": reason
23 }
24 }
25
26 if user_prompt:
27 output["hookSpecificOutput"]["userPrompt"] = user_prompt
28
29 if system_message:
30 output["systemMessage"] = system_message
31
32 if suppress_output:
33 output["suppressOutput"] = True
34
35 return output型別別名
為複雜型別建立別名提升可讀性:
1from typing import Dict, List, Tuple
2
3# 定義型別別名
4ValidationResult = Tuple[bool, str]
5ConfigDict = Dict[str, Any]
6NameList = List[str]
7
8# 使用別名
9def validate_input(data: str) -> ValidationResult:
10 if data:
11 return True, "Valid"
12 return False, "Empty input"
13
14def load_config() -> ConfigDict:
15 return {"key": "value"}型別檢查工具
型別提示本身不會在執行時檢查,但可以用工具進行靜態檢查:
mypy
1# 安裝
2pip install mypy
3
4# 檢查檔案
5mypy my_script.py
6
7# 檢查目錄
8mypy .claude/lib/IDE 整合
現代 IDE(VS Code、PyCharm)會自動利用型別提示:
- 自動完成更準確
- 型別錯誤即時提示
- 重構更安全
最佳實踐
1. 為公開 API 添加型別提示
1# 公開函式必須有型別提示
2def get_current_branch() -> Optional[str]:
3 """獲取當前分支名稱"""
4 ...
5
6# 內部輔助函式可以省略
7def _parse_output(text):
8 ...2. 使用有意義的型別別名
1# 好:清楚表達意圖
2BranchName = str
3ValidationResult = Tuple[bool, str]
4
5def validate_branch(name: BranchName) -> ValidationResult:
6 ...
7
8# 不好:型別別名沒有增加資訊
9MyStr = str # 這有什麼意義?3. 逐步添加型別提示
不需要一次為所有程式碼添加型別提示,可以從以下開始:
- 公開 API
- 複雜函式
- 經常被呼叫的函式
思考題
list[str]和List[str]有什麼區別?什麼時候用哪個?- 為什麼
run_git_command返回tuple[bool, str]而不是自定義類別? - 型別提示會影響程式執行速度嗎?
實作練習
為以下函式添加適當的型別提示:
1def parse_config(file_path):
2 with open(file_path) as f:
3 return json.load(f)
4
5def filter_valid_items(items):
6 return [item for item in items if item.get("valid")]
7
8def merge_dicts(dict1, dict2):
9 result = dict1.copy()
10 result.update(dict2)
11 return result