Python Type Hint 型別註解教學 - 泛型
本文介紹如何在 Python 中使用泛型,前一篇文章的高階使用已經很少用了,這裡更用不到。
泛型
重點終於來了!最開始原本只想寫這裡的,不過現在反而變成可跳過了,因為連 mypy 這個專門做靜態檢查的工具都表示跳過泛型完全沒差。
什麼是泛型?
用於創建可以操作多種型別的函式或類別,無需針對每種特定型別重複實作。這使得程式碼更具彈性、可重複利用,同時保證型別安全。當使用泛型時,可以讓類別或函式在實例化或調用時根據指定的型別參數進行型別推斷,從而在編譯或靜態檢查階段檢測不符合型別的操作。
一句話解釋:實例化後才決定使用的變數,避免重複撰寫相似程式,同時確保型別安全。
TypeVar
Python 中的泛型,用於標示尚未決定的型別,實例化該「函式」後就可以限制 T
只能使用相同的型別。
from typing import List, TypeVar
T = TypeVar("T")
def concat(a: List[T], b: T) -> List[T]:
return a + [b] # 把 b 合併進 list a
# 故意混用不同型別
numbers: List[int] = [1, 2, 3]
text: str = "hello"
# mypy 會在這行報錯,因為 T 不能同時是 int 和 str
result = concat(numbers, text) # error: Cannot infer type argument 1 of "concatenate" [misc]
print(result) # [1, 2, 3, 'hello']
TypeVar 也有參數,使用方式為
bound
T = TypeVar("T", int, str) # 限制只能使用 int/str
T = TypeVar("T", int, str, bound=MyClass) # 限制只能使用 int/str 和 MyClass 的子類別
covariant
設定使否使用協變,協變代表允許子類型替代父類型
T_co = TypeVar('T_co', covariant=True)
contravariant
設定使否使用逆變,逆變代表允許父類型替代子類型
T_co = TypeVar('T_co', contravariant=True)
由於協變逆變筆者也是第一次接觸,所以請語言模型生成了一個範例
ChatGPT 4o#2024/11
協變與逆變在型別系統中決定了如何處理繼承關係中的類型約束,特別在泛型和繼承類別中的參數傳遞上起著至關重要的作用。Python 透過 typing
模組支持協變(covariant)與逆變(contravariant),特別用於類型參數的方向性控制,使我們能更靈活地進行類型檢查和靜態分析。這裡提供一個清晰的範例,展示設定協變與逆變如何影響程式的行為和安全性。
協變與逆變的概念
- 協變(Covariant):允許子類型替代父類型,例如,
List[Dog]
可以視為List[Animal]
。 - 逆變(Contravariant)