Python3中typing模块介绍
? ? ? typing.py的源碼在:https://github.com/python/cpython/blob/main/Lib/typing.py。此模塊為類型提示(Type Hints)提供運行時支持(This module provides runtime support for type hints)。從python 3.5版本開始將Typing作為標準庫引入。
? ? ? python3中增加了Function Annotation(函數注解,能夠聲明類型)的功能,可以使用類型檢查工具如mypy達到類型靜態檢查的效果。
? ? ? 類型提示對于運行實際上沒有任何影響。
? ? ? Type aliases:類型別名是通過將類型分配給別名來定義的。類型別名可用于簡化復雜類型簽名。
# Vector和List[float]將被視為可互換的同義詞
Vector = List[float]def scale(scalar: float, vector: Vector) -> Vector:return [scalar * num for num in vector]# a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4]); print(new_vector) # [2.0, -8.4, 10.8]
? ? ? NewType:使用NewType輔助類來創建不同的類型。靜態類型檢查器會將新類型視為原始類型的子類,這有助于捕獲邏輯錯誤。
UserId = NewType('UserId', int) # 實際上UserID就是一個int類型,可以對其像int一樣正常操作
some_id = UserId(524313); print(some_id) # 524313def get_user_name(user_id: UserId) -> str:return str(user_id)user_a = get_user_name(UserId(42351)); print(user_a) # 42351# 可以對UserId類型的變量執行所有int操作,但結果始終為int類型
output = UserId(23413) + UserId(54341); print(output) # 77754
? ? ? Any:是一種特殊的類型。靜態類型檢查器會將每種類型都視為與Any兼容,同樣,Any也與所有類型兼容。可以對Any類型的值執行任何操作或方法調用,并將其分配給任何變量。將Any類型的值分配給更精確的類型(more precise type)時,不會執行類型檢查。所有沒有返回類型或參數類型的函數都將隱式地默認使用Any。
? ? ? Any與object的區別:與Any類似,每個類型都是object的子類型。然而,與Any不同,反過來就不成立了:object不是其它類型的子類型。
? ? ? 使用object,說明值能以類型安全的方式轉為任何類型;使用Any,說明值是動態類型。
a: Any = None
a = [] # OK
a = 2 # OKs: str = ""
s = a # OK
print(s) # 2
? ? ? NoReturn:特殊類型,標記一個函數沒有返回值
def stop() -> NoReturn:raise RuntimeError('no way')stop()
? ? ? Union:聯合類型,Union[X, Y]等價于X|Y,意味著X或Y。使用形如Union[int, str]的形式來定義一個聯合體:(1).參數必須是某種類型,且至少有一個;(2).聯合類型的聯合類型會被展開(flattened);(3).僅有一個參數的聯合類型就是該參數自身;(4).冗余的參數會被跳過(skipped);(5).在比較聯合類型的時候,參數順序會被忽略(ignored);(6).不能繼承或者實例化一個聯合類型;(7).不支持Union[X][Y]這種寫法。
# 聯合類型的聯合類型會被展開(flattened)
Union[Union[int, str], float] == Union[int, str, float]
# 僅有一個參數的聯合類型就是該參數自身
Union[int] == int
# 冗余的參數會被跳過(skipped)
Union[int, str, int] == Union[int, str] # == int | str
# 在比較聯合類型的時候,參數順序會被忽略(ignored)
Union[int, str] == Union[str, int]
? ? ? Optional:可選類型,Optional[X]等價于X|None,或Union[X, None]。可選類型與含默認值的可選參數不同,含默認值的可選參數不需要在類型注解(type annotation)上添加Optional限定符,因為它僅是可選的。顯式應用None值時,不管該參數是否可選,Optional都適用。
# 可選類型與含默認值的可選參數不同,含默認值的可選參數不需要在類型注解(type annotation)上添加Optional限定符,因為它僅是可選的
def foo(arg: int = 0) -> None: ...
# 顯式應用None值時,不管該參數是否可選,Optional都適用
def foo(arg: Optional[int] = None) -> None: ...
? ? ? Callable:可調用類型,下標語法(subscription syntax)必須始終與兩個值一起使用:參數列表和返回類型。參數列表必須是類型列表或省略號;返回類型必須是單一類型。如:Callable[[int], str]
? ? ? 沒有指示可選參數或關鍵字參數的語法,這種函數類型很少用作回調類型。Callable[…, ReturnType]可用于類型提示一個可調用的接受任意數量的參數并返回ReturnType。一個普通的Callable等價于Callable[…, Any]。
? ? ? 將其它可調用對象作為參數的可調用對象可能表明它們的參數類型使用typing.ParamSpec相互依賴。此外,如果該可調用對象從其它可調用對象中添加或刪除參數,則可以使用typing.Concatenate運算符。
def other_function(x: int, y: float) -> float:print(f"x: {x}, y: {y}")return ydef any_function(func: Callable[[int, float], float], x: int, y: float) -> float:return func(x, y)any_function(other_function, x=10, y=20)
any_function(other_function, x="abc", y=20) # 注:此條語句可以正常執行,類型提示(type hints)對運行實際上是沒有影響的def get_addr(csdn: str, github: str, port: int=403) -> str:return f"csdn: {csdn}, github: {github}, port: {port}"def get_addr() -> Callable[[str, str, int], str]:return get_addr
? ? ? Literal:字面類型,可用于向類型檢查器指示相應的變量或函數參數與提供的字面量(或多個字面量之一)等效的值。Literal[…]不能創建子類。在運行時,允許將任意值作為Literal[…]的類型參數,但類型檢查器可能會對此加以限制。
def validate_simple(data: Any) -> Literal[True]: ... # always returns TrueMODE = Literal["r", "rb", "w", "wb"]
def open_helper(file: str, mode: MODE) -> str:return file + ":" + modeprint(open_helper("/some/path", "r")) # /some/path:r
? ? ? TypeVar:容器中,對象的類型信息不能以Generic(泛型)方式靜態推斷,因此,抽象基類擴展支持下標(subscription),用于表示容器元素的預期類型。可以使用typing模塊中的TypeVar新工廠實現Generic參數化:(1).用戶定義的類可以定義為Generic類;(2). Generic類型支持多個類型變量,不過,類型變量可能會受到限制;(3). Generic類型變量的參數都必須是不同的;(4).Generic支持多重繼承;(5).從Generic類繼承時,可以修復一些類型變量;(6).使用Generic類而不指定類型參數時,每個位置的類型都預設為Any。
T = TypeVar('T') # Declare type variable, Can be anything
# 泛型類型支持多個類型變量,不過,類型變量可能會受到限制
S = TypeVar('S', int, str) # Must be int or strclass StrangePair(Generic[T, S]): ...# 泛型類型變量的參數都必須是不同的
#class Pair(Generic[T, T]): ... # TypeError: Parameters to Generic[...] must all be uniquelength = "5.5"
Length = TypeVar("Length", int, float, None) # Length可以使用int, float或None來表示
def get_length() -> Length:return lengthprint(get_length()) # 5.5
? ? ? TypedDict:把類型提示(type hints)添加到字典的特殊構造(special construct)。在運行時,它是一個普通的dict。TypedDict聲明一個字典類型,該類型期望它的所有實例都有一組固定的keys,其中每個key都與對應類型的值關聯。這種期望不會在運行時檢查,而只會由類型檢查器強制執行。默認情況下,所有的keys都必須出現在一個TypedDict中,可以通過指定總體(totality)來重寫它。
class Point2D(TypedDict):x: inty: intlabel: stra: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK
b: Point2D = {'z': 3, 'label': 'bad'} # Fails type checkassert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')
? ? ? Dict:dict的泛型(generic)版本,用于注解(annotate)返回類型。注解參數時,最好使用抽象集合類型(abstract collection type),例如Mapping。Dict與dict之間沒有真正的區別,但是Dict是泛型類型,它允許你指定key和value的類型,使其更加靈活。
def count_words(text: str) -> Dict[str, int]: ...
x: Dict[str, int] = {"beijing", 1}; print(x) # {"beijing", 1}
? ? ? Mapping:collections.abc.Mapping的泛型(generic)版本。
def get_position_in_index(word_list: Mapping[str, int], word: str) -> int:return word_list[word]def func(m: Mapping[int, str]) -> List[int]:return list(m.keys())print(func({0: "no", 1: "yes"})) # [0, 1]
? ? ? List:list的泛型(generic)版本,用于注解(annotate)返回類型。注解參數時,最好使用抽象集合類型(abstract collection type),例如Sequence或Iterable。
T = TypeVar('T', int, float)def vec2(x: T, y: T) -> List[T]:return [x, y]print(vec2(3, 2)) # [3, 2]def keep_positives(vector: Sequence[T]) -> List[T]:return [item for item in vector if item > 0]x: List[int] = [1, 2, 3]; print(x) # [1, 2, 3]
? ? ? Tuple:元組類型,Tuple[X, Y]是二項的元組類型,第一個元素的類型是X,第二個元素的類型是Y。空元組的類型可以寫為Tuple[()]。如Tuple[int, float, str]是由整數、浮點數、字符串組成的三項元組。可用字面省略號(literal ellipsis)指定可變長元組,如Tuple[int, …]。
# 指定所有元素的類型
x: Tuple[int, float, str] = (1, 2.1, "beijing"); print(x) # (1, 2.1, "beijing")
# 可變長度的元組
y: Tuple[int, ...] = (1, 2.1, "beijing"); print(y) # (1, 2.1, "beijing")
? ? ? Set:builtins.set的泛型版本,用于注解返回類型。注解參數時,最好使用抽象集合類型,例如AbstractSet。
x: Set[int] = {1, 2, 3}; print(x) # {1, 2, 3}
? ? ? AbstractSet:collections.abc.Set的泛型版本。
? ? ? Deque:collections.deque的泛型版本。
? ? ? Sequence:collections.abc.Sequence的泛型版本。
? ? ? Iterable:collections.abc.Iterator的泛型版本。
def func(l: Iterable[int]) -> List[str]:return [str(x) for x in l]print(func(range(1, 5))) # ['1', '2', '3', '4']
? ? ? overload:參考:https://blog.csdn.net/fengbingchun/article/details/121959036
? ? ? 以上內容主要參考:https://docs.python.org/3/library/typing.html
? ? ? GitHub:https://github.com/fengbingchun/Python_Test
總結
以上是生活随笔為你收集整理的Python3中typing模块介绍的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python3中内置函数callable
- 下一篇: Python3中__call__方法介绍