typing
— 型別提示支援¶
在 3.5 版本加入。
原始碼: Lib/typing.py
備註
Python 執行時不強制函式和變數型別註解。它們可以被第三方工具使用,例如型別檢查器、IDE、linter 等。
本模組為型別提示提供執行時支援。
考慮下面的函式
def surface_area_of_cube(edge_length: float) -> str:
return f"The surface area of the cube is {6 * edge_length ** 2}."
函式 surface_area_of_cube
接受一個預期為 float
例項的引數,如型別提示 edge_length: float
所示。該函式預期返回一個 str
例項,如 -> str
提示所示。
雖然型別提示可以是簡單的類,如 float
或 str
,但它們也可以更復雜。typing
模組提供了更高階的型別提示詞彙表。
typing
模組經常新增新功能。typing_extensions 包為舊版本的 Python 提供了這些新功能的向後移植。
參見
- 型別提示速查表
型別提示的快速概覽(託管在 mypy 文件中)
- mypy 文件的型別系統參考部分
Python 型別系統透過 PEPs 進行標準化,因此本參考資料應廣泛適用於大多數 Python 型別檢查器。(某些部分可能仍然特定於 mypy。)
- Python 靜態型別
由社群編寫的與型別檢查器無關的文件,詳細介紹了型別系統功能、有用的型別相關工具和型別提示最佳實踐。
Python 型別系統規範¶
Python 型別系統的規範(規範、最新)可在Python 型別系統規範中找到。
類型別名¶
類型別名使用 type
語句定義,該語句建立 TypeAliasType
的例項。在此示例中,Vector
和 list[float]
將被靜態型別檢查器同等對待。
type Vector = list[float]
def scale(scalar: float, vector: Vector) -> Vector:
return [scalar * num for num in vector]
# passes type checking; a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])
類型別名對於簡化複雜的型別簽名非常有用。例如
from collections.abc import Sequence
type ConnectionOptions = dict[str, str]
type Address = tuple[str, int]
type Server = tuple[Address, ConnectionOptions]
def broadcast_message(message: str, servers: Sequence[Server]) -> None:
...
# The static type checker will treat the previous type signature as
# being exactly equivalent to this one.
def broadcast_message(
message: str,
servers: Sequence[tuple[tuple[str, int], dict[str, str]]]
) -> None:
...
type
語句是 Python 3.12 中的新功能。為了向後相容,類型別名也可以透過簡單賦值建立
Vector = list[float]
或者用 TypeAlias
標記,以明確這是一個類型別名,而不是一個普通變數賦值。
from typing import TypeAlias
Vector: TypeAlias = list[float]
NewType¶
使用 NewType
輔助函式建立不同的型別
from typing import NewType
UserId = NewType('UserId', int)
some_id = UserId(524313)
靜態型別檢查器會將新型別視為原始型別的子類。這有助於捕獲邏輯錯誤
def get_user_name(user_id: UserId) -> str:
...
# passes type checking
user_a = get_user_name(UserId(42351))
# fails type checking; an int is not a UserId
user_b = get_user_name(-1)
您仍然可以在 UserId
型別的變數上執行所有 int
操作,但結果始終是 int
型別。這允許您在預期 int
的任何地方傳入 UserId
,但會阻止您以無效方式意外建立 UserId
。
# 'output' is of type 'int', not 'UserId'
output = UserId(23413) + UserId(54341)
請注意,這些檢查僅由靜態型別檢查器強制執行。在執行時,語句 Derived = NewType('Derived', Base)
將使 Derived
成為一個可呼叫物件,它會立即返回您傳入的任何引數。這意味著表示式 Derived(some_value)
不會建立新類,也不會引入超出常規函式呼叫的大量開銷。
更準確地說,表示式 some_value is Derived(some_value)
在執行時始終為真。
建立 Derived
的子型別是無效的
from typing import NewType
UserId = NewType('UserId', int)
# Fails at runtime and does not pass type checking
class AdminUserId(UserId): pass
但是,可以基於“派生”的 NewType
建立 NewType
from typing import NewType
UserId = NewType('UserId', int)
ProUserId = NewType('ProUserId', UserId)
並且 ProUserId
的型別檢查將按預期工作。
有關更多詳細資訊,請參閱 PEP 484。
備註
回想一下,使用類型別名聲明瞭兩個型別是 等價的 。執行 type Alias = Original
將使靜態型別檢查器在所有情況下都將 Alias
視為與 Original
完全等價 。當您想簡化複雜的型別簽名時,這很有用。
相反,NewType
聲明瞭一個型別是另一個型別的 子型別 。執行 Derived = NewType('Derived', Original)
將使靜態型別檢查器將 Derived
視為 Original
的 子類 ,這意味著型別為 Original
的值不能用於預期型別為 Derived
的位置。當您想以最小的執行時成本防止邏輯錯誤時,這很有用。
3.5.2 版本新增。
3.10 版本中的更改: NewType
現在是一個類而不是一個函式。因此,與常規函式呼叫相比,呼叫 NewType
會產生一些額外的執行時成本。
3.11 版本中的更改: 呼叫 NewType
的效能已恢復到 Python 3.9 的水平。
註解可呼叫物件¶
函式——或其他可呼叫物件——可以使用 collections.abc.Callable
或已棄用的 typing.Callable
進行註解。Callable[[int], str]
表示一個接受一個 int
型別的引數並返回 str
的函式。
例如:
from collections.abc import Callable, Awaitable
def feeder(get_next_item: Callable[[], str]) -> None:
... # Body
def async_query(on_success: Callable[[int], None],
on_error: Callable[[int, Exception], None]) -> None:
... # Body
async def on_update(value: str) -> None:
... # Body
callback: Callable[[str], Awaitable[None]] = on_update
訂閱語法必須始終與恰好兩個值一起使用:引數列表和返回型別。引數列表必須是型別列表、ParamSpec
、Concatenate
或省略號(...
)。返回型別必須是單個型別。
如果引數列表給定字面省略號 ...
,則表示接受具有任意引數列表的可呼叫物件。
def concat(x: str, y: str) -> str:
return x + y
x: Callable[..., str]
x = str # OK
x = concat # Also OK
Callable
無法表達複雜的簽名,例如接受可變數量引數的函式、過載函式或具有僅關鍵字引數的函式。但是,可以透過定義具有 __call__()
方法的 Protocol
類來表達這些簽名
from collections.abc import Iterable
from typing import Protocol
class Combiner(Protocol):
def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ...
def batch_proc(data: Iterable[bytes], cb_results: Combiner) -> bytes:
for item in data:
...
def good_cb(*vals: bytes, maxlen: int | None = None) -> list[bytes]:
...
def bad_cb(*vals: bytes, maxitems: int | None) -> list[bytes]:
...
batch_proc([], good_cb) # OK
batch_proc([], bad_cb) # Error! Argument 2 has incompatible type because of
# different name and kind in the callback
接受其他可呼叫物件作為引數的可呼叫物件可以使用 ParamSpec
指示它們的引數型別相互依賴。此外,如果該可呼叫物件新增或刪除其他可呼叫物件的引數,則可以使用 Concatenate
運算子。它們的形式分別為 Callable[ParamSpecVariable, ReturnType]
和 Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType]
。
3.10 版本中的更改: Callable
現在支援 ParamSpec
和 Concatenate
。有關更多詳細資訊,請參閱 PEP 612。
參見
ParamSpec
和 Concatenate
的文件提供了 Callable
中的用法示例。
泛型¶
由於無法以通用方式靜態推斷容器中物件的型別資訊,標準庫中的許多容器類都支援訂閱來表示容器元素的預期型別。
from collections.abc import Mapping, Sequence
class Employee: ...
# Sequence[Employee] indicates that all elements in the sequence
# must be instances of "Employee".
# Mapping[str, str] indicates that all keys and all values in the mapping
# must be strings.
def notify_by_email(employees: Sequence[Employee],
overrides: Mapping[str, str]) -> None: ...
泛型函式和類可以使用型別引數語法進行引數化。
from collections.abc import Sequence
def first[T](l: Sequence[T]) -> T: # Function is generic over the TypeVar "T"
return l[0]
或者直接使用 TypeVar
工廠
from collections.abc import Sequence
from typing import TypeVar
U = TypeVar('U') # Declare type variable "U"
def second(l: Sequence[U]) -> U: # Function is generic over the TypeVar "U"
return l[1]
3.12 版本中的更改: 泛型的語法支援是 Python 3.12 中的新功能。
註解元組¶
對於 Python 中的大多數容器,型別系統假定容器中的所有元素都具有相同的型別。例如
from collections.abc import Mapping
# Type checker will infer that all elements in ``x`` are meant to be ints
x: list[int] = []
# Type checker error: ``list`` only accepts a single type argument:
y: list[int, str] = [1, 'foo']
# Type checker will infer that all keys in ``z`` are meant to be strings,
# and that all values in ``z`` are meant to be either strings or ints
z: Mapping[str, str | int] = {}
list
只接受一個型別引數,因此型別檢查器將在上面的 y
賦值上發出錯誤。類似地,Mapping
只接受兩個型別引數:第一個表示鍵的型別,第二個表示值的型別。
然而,與其他大多數 Python 容器不同,在地道的 Python 程式碼中,元組的元素不都是相同型別是很常見的。因此,元組在 Python 的型別系統中是特殊處理的。tuple
接受 任意數量 的型別引數
# OK: ``x`` is assigned to a tuple of length 1 where the sole element is an int
x: tuple[int] = (5,)
# OK: ``y`` is assigned to a tuple of length 2;
# element 1 is an int, element 2 is a str
y: tuple[int, str] = (5, "foo")
# Error: the type annotation indicates a tuple of length 1,
# but ``z`` has been assigned to a tuple of length 3
z: tuple[int] = (1, 2, 3)
要表示長度 任意 且所有元素都具有相同型別 T
的元組,請使用字面省略號 ...
:tuple[T, ...]
。要表示空元組,請使用 tuple[()]
。使用純 tuple
作為註解等同於使用 tuple[Any, ...]
。
x: tuple[int, ...] = (1, 2)
# These reassignments are OK: ``tuple[int, ...]`` indicates x can be of any length
x = (1, 2, 3)
x = ()
# This reassignment is an error: all elements in ``x`` must be ints
x = ("foo", "bar")
# ``y`` can only ever be assigned to an empty tuple
y: tuple[()] = ()
z: tuple = ("foo", "bar")
# These reassignments are OK: plain ``tuple`` is equivalent to ``tuple[Any, ...]``
z = (1, 2, 3)
z = ()
類物件的型別¶
使用 C
註解的變數可以接受型別為 C
的值。相反,使用 type[C]
(或已棄用的 typing.Type[C]
)註解的變數可以接受本身就是類的值——具體來說,它將接受 C
的 類物件。例如
a = 3 # Has type ``int``
b = int # Has type ``type[int]``
c = type(a) # Also has type ``type[int]``
請注意,type[C]
是協變的
class User: ...
class ProUser(User): ...
class TeamUser(User): ...
def make_new_user(user_class: type[User]) -> User:
# ...
return user_class()
make_new_user(User) # OK
make_new_user(ProUser) # Also OK: ``type[ProUser]`` is a subtype of ``type[User]``
make_new_user(TeamUser) # Still fine
make_new_user(User()) # Error: expected ``type[User]`` but got ``User``
make_new_user(int) # Error: ``type[int]`` is not a subtype of ``type[User]``
type
的唯一合法引數是類、Any
、型別變數以及這些型別中的任意一種的聯合。例如
def new_non_team_user(user_class: type[BasicUser | ProUser]): ...
new_non_team_user(BasicUser) # OK
new_non_team_user(ProUser) # OK
new_non_team_user(TeamUser) # Error: ``type[TeamUser]`` is not a subtype
# of ``type[BasicUser | ProUser]``
new_non_team_user(User) # Also an error
註解生成器和協程¶
生成器可以使用泛型型別 Generator[YieldType, SendType, ReturnType]
進行註解。例如
def echo_round() -> Generator[int, float, str]:
sent = yield 0
while sent >= 0:
sent = yield round(sent)
return 'Done'
請注意,與標準庫中許多其他泛型類不同,Generator
的 SendType
行為是逆變而不是協變或不變。
SendType
和 ReturnType
引數預設為 None
def infinite_stream(start: int) -> Generator[int]:
while True:
yield start
start += 1
也可以明確設定這些型別
def infinite_stream(start: int) -> Generator[int, None, None]:
while True:
yield start
start += 1
僅生成值的簡單生成器也可以註解為返回型別為 Iterable[YieldType]
或 Iterator[YieldType]
def infinite_stream(start: int) -> Iterator[int]:
while True:
yield start
start += 1
非同步生成器以類似的方式處理,但不期望 ReturnType
型別引數(AsyncGenerator[YieldType, SendType]
)。SendType
引數預設為 None
,因此以下定義是等價的
async def infinite_stream(start: int) -> AsyncGenerator[int]:
while True:
yield start
start = await increment(start)
async def infinite_stream(start: int) -> AsyncGenerator[int, None]:
while True:
yield start
start = await increment(start)
與同步情況一樣,AsyncIterable[YieldType]
和 AsyncIterator[YieldType]
也可用
async def infinite_stream(start: int) -> AsyncIterator[int]:
while True:
yield start
start = await increment(start)
協程可以使用 Coroutine[YieldType, SendType, ReturnType]
進行註解。泛型引數與 Generator
的引數相對應,例如
from collections.abc import Coroutine
c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere
x = c.send('hi') # Inferred type of 'x' is list[str]
async def bar() -> None:
y = await c # Inferred type of 'y' is int
使用者定義的泛型型別¶
使用者定義的類可以定義為泛型類。
from logging import Logger
class LoggedVar[T]:
def __init__(self, value: T, name: str, logger: Logger) -> None:
self.name = name
self.logger = logger
self.value = value
def set(self, new: T) -> None:
self.log('Set ' + repr(self.value))
self.value = new
def get(self) -> T:
self.log('Get ' + repr(self.value))
return self.value
def log(self, message: str) -> None:
self.logger.info('%s: %s', self.name, message)
此語法表示類 LoggedVar
是圍繞單個 型別變數 T
引數化的。這也使得 T
在類主體內作為型別有效。
泛型類隱式繼承自 Generic
。為了與 Python 3.11 及更低版本相容,也可以顯式繼承自 Generic
以指示泛型類。
from typing import TypeVar, Generic
T = TypeVar('T')
class LoggedVar(Generic[T]):
...
泛型類具有 __class_getitem__()
方法,這意味著它們可以在執行時進行引數化(例如下面的 LoggedVar[int]
)
from collections.abc import Iterable
def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
for var in vars:
var.set(0)
泛型型別可以有任意數量的型別變數。TypeVar
的所有變體都可以作為泛型型別的引數
from typing import TypeVar, Generic, Sequence
class WeirdTrio[T, B: Sequence[bytes], S: (int, str)]:
...
OldT = TypeVar('OldT', contravariant=True)
OldB = TypeVar('OldB', bound=Sequence[bytes], covariant=True)
OldS = TypeVar('OldS', int, str)
class OldWeirdTrio(Generic[OldT, OldB, OldS]):
...
傳遞給 Generic
的每個型別變數引數都必須是唯一的。因此,這是無效的
from typing import TypeVar, Generic
...
class Pair[M, M]: # SyntaxError
...
T = TypeVar('T')
class Pair(Generic[T, T]): # INVALID
...
泛型類也可以繼承自其他類
from collections.abc import Sized
class LinkedList[T](Sized):
...
繼承泛型類時,某些型別引數可以固定。
from collections.abc import Mapping
class MyDict[T](Mapping[str, T]):
...
在這種情況下,MyDict
有一個引數,T
。
使用不指定型別引數的泛型類將為每個位置假定 Any
。在以下示例中,MyIterable
不是泛型類,但隱式繼承自 Iterable[Any]
。
from collections.abc import Iterable
class MyIterable(Iterable): # Same as Iterable[Any]
...
也支援使用者定義的泛型類型別名。例如
from collections.abc import Iterable
type Response[S] = Iterable[S] | int
# Return type here is same as Iterable[str] | int
def response(query: str) -> Response[str]:
...
type Vec[T] = Iterable[tuple[T, T]]
def inproduct[T: (int, float, complex)](v: Vec[T]) -> T: # Same as Iterable[tuple[T, T]]
return sum(x*y for x, y in v)
為了向後相容,泛型類型別名也可以透過簡單賦值建立。
from collections.abc import Iterable
from typing import TypeVar
S = TypeVar("S")
Response = Iterable[S] | int
3.7 版本中的更改: Generic
不再具有自定義元類。
3.12 版本中的更改: 泛型和類型別名的語法支援是 3.12 版本中的新功能。以前,泛型類必須顯式繼承自 Generic
或在其某個基類中包含型別變數。
還透過引數規範變數以 [**P]
形式支援用於引數表示式的使用者定義泛型。其行為與上面描述的型別變數一致,因為 typing
模組將引數規範變數視為特殊化的型別變數。唯一的例外是可以使用型別列表來替換 ParamSpec
。
>>> class Z[T, **P]: ... # T is a TypeVar; P is a ParamSpec
...
>>> Z[int, [dict, float]]
__main__.Z[int, [dict, float]]
泛型類 over ParamSpec
也可以透過顯式繼承自 Generic
建立。在這種情況下,不使用 **
。
from typing import ParamSpec, Generic
P = ParamSpec('P')
class Z(Generic[P]):
...
TypeVar
和 ParamSpec
之間的另一個區別是,只有一個引數規範變數的泛型將接受 X[[Type1, Type2, ...]]
形式的引數列表,以及出於美觀原因的 X[Type1, Type2, ...]
形式。在內部,後者被轉換為前者,因此以下兩者是等價的
>>> class X[**P]: ...
...
>>> X[int, str]
__main__.X[[int, str]]
>>> X[[int, str]]
__main__.X[[int, str]]
請注意,帶有 ParamSpec
的泛型在某些情況下在替換後可能沒有正確的 __parameters__
,因為它們主要用於靜態型別檢查。
使用者定義的泛型類可以具有 ABCs 作為基類,而不會發生元類衝突。不支援泛型元類。引數化泛型的結果被快取,並且 typing
模組中的大多數型別都是可雜湊的並且在相等性方面可比較。
Any
型別¶
一種特殊型別的型別是 Any
。靜態型別檢查器將把所有型別視為與 Any
相容,並將 Any
視為與所有型別相容。
這意味著可以對 Any
型別的值執行任何操作或方法呼叫,並將其賦值給任何變數。
from typing import Any
a: Any = None
a = [] # OK
a = 2 # OK
s: str = ''
s = a # OK
def foo(item: Any) -> int:
# Passes type checking; 'item' could be any type,
# and that type might have a 'bar' method
item.bar()
...
請注意,將 Any
型別的值分配給更精確的型別時,不會執行型別檢查。例如,即使 s
被宣告為 str
型別,並在執行時接收到一個 int
值,靜態型別檢查器在將 a
分配給 s
時也沒有報告錯誤!
此外,所有沒有返回型別或引數型別的函式將隱式預設使用 Any
。
def legacy_parser(text):
...
return data
# A static type checker will treat the above
# as having the same signature as:
def legacy_parser(text: Any) -> Any:
...
return data
這種行為允許 Any
作為 逃逸出口 使用,當您需要混合動態和靜態型別程式碼時。
將 Any
的行為與 object
的行為進行對比。與 Any
類似,所有型別都是 object
的子型別。然而,與 Any
不同,反之則不然:object
不是 所有其他型別的子型別。
這意味著當一個值的型別是 object
時,型別檢查器將拒絕對其進行幾乎所有操作,將其分配給更專業型別的變數(或將其用作返回值)將是型別錯誤。例如
def hash_a(item: object) -> int:
# Fails type checking; an object does not have a 'magic' method.
item.magic()
...
def hash_b(item: Any) -> int:
# Passes type checking
item.magic()
...
# Passes type checking, since ints and strs are subclasses of object
hash_a(42)
hash_a("foo")
# Passes type checking, since Any is compatible with all types
hash_b(42)
hash_b("foo")
名義子型別與結構子型別¶
最初 PEP 484 將 Python 靜態型別系統定義為使用 名義子型別。這意味著如果且僅當 A
是 B
的子類時,允許在預期類 B
的位置使用類 A
。
此要求以前也適用於抽象基類,例如 Iterable
。這種方法的缺點是類必須明確標記以支援它們,這不符合 Python 風格,也不像在習慣的動態型別 Python 程式碼中通常會做的那樣。例如,這符合 PEP 484
from collections.abc import Sized, Iterable, Iterator
class Bucket(Sized, Iterable[int]):
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
PEP 544 允許透過允許使用者在類定義中編寫上述程式碼而無需顯式基類來解決此問題,從而允許靜態型別檢查器將 Bucket
隱式視為 Sized
和 Iterable[int]
的子型別。這被稱為 結構子型別(或靜態鴨子型別)。
from collections.abc import Iterator, Iterable
class Bucket: # Note: no base classes
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
def collect(items: Iterable[int]) -> int: ...
result = collect(Bucket()) # Passes type check
此外,透過繼承特殊的類 Protocol
,使用者可以定義新的自定義協議以充分利用結構子型別(參見下面的示例)。
模組內容¶
typing
模組定義了以下類、函式和裝飾器。
特殊型別提示原語¶
特殊型別¶
這些可用作註解中的型別。它們不支援使用 []
進行訂閱。
- typing.AnyStr¶
一個 受限型別變數。
定義
AnyStr = TypeVar('AnyStr', str, bytes)
AnyStr
旨在用於可能接受str
或bytes
引數但不能允許兩者混用的函式。例如:
def concat(a: AnyStr, b: AnyStr) -> AnyStr: return a + b concat("foo", "bar") # OK, output has type 'str' concat(b"foo", b"bar") # OK, output has type 'bytes' concat("foo", b"bar") # Error, cannot mix str and bytes
請注意,儘管其名稱如此,
AnyStr
與Any
型別無關,也不表示“任何字串”。特別是,AnyStr
和str | bytes
彼此不同,並且具有不同的用例# Invalid use of AnyStr: # The type variable is used only once in the function signature, # so cannot be "solved" by the type checker def greet_bad(cond: bool) -> AnyStr: return "hi there!" if cond else b"greetings!" # The better way of annotating this function: def greet_proper(cond: bool) -> str | bytes: return "hi there!" if cond else b"greetings!"
- typing.LiteralString¶
只包含字面字串的特殊型別。
任何字串字面量都與
LiteralString
相容,另一個LiteralString
也是如此。但是,僅鍵入為str
的物件則不相容。透過組合LiteralString
型別的物件建立的字串也可用作LiteralString
。示例
def run_query(sql: LiteralString) -> None: ... def caller(arbitrary_string: str, literal_string: LiteralString) -> None: run_query("SELECT * FROM students") # OK run_query(literal_string) # OK run_query("SELECT * FROM " + literal_string) # OK run_query(arbitrary_string) # type checker error run_query( # type checker error f"SELECT * FROM students WHERE name = {arbitrary_string}" )
LiteralString
對於敏感的 API 很有用,其中任意使用者生成的字串可能會產生問題。例如,上面兩個會生成型別檢查器錯誤的案例可能會受到 SQL 注入攻擊。有關更多詳細資訊,請參閱 PEP 675。
在 3.11 版本中新增。
- typing.Never¶
- typing.NoReturn¶
Never
和NoReturn
代表 底部型別,一個沒有成員的型別。它們可用於指示函式永不返回,例如
sys.exit()
。from typing import Never # or NoReturn def stop() -> Never: raise RuntimeError('no way')
或者定義一個永遠不應被呼叫的函式,因為沒有有效的引數,例如
assert_never()
。from typing import Never # or NoReturn def never_call_me(arg: Never) -> None: pass def int_or_str(arg: int | str) -> None: never_call_me(arg) # type checker error match arg: case int(): print("It's an int") case str(): print("It's a str") case _: never_call_me(arg) # OK, arg is of type Never (or NoReturn)
Never
和NoReturn
在型別系統中具有相同的含義,靜態型別檢查器將兩者同等對待。3.6.2 版本新增: 增加了
NoReturn
。3.11 版本新增: 增加了
Never
。
- typing.Self¶
表示當前封閉類的特殊型別。
例如:
from typing import Self, reveal_type class Foo: def return_self(self) -> Self: ... return self class SubclassOfFoo(Foo): pass reveal_type(Foo().return_self()) # Revealed type is "Foo" reveal_type(SubclassOfFoo().return_self()) # Revealed type is "SubclassOfFoo"
此註解在語義上等同於以下內容,儘管方式更簡潔
from typing import TypeVar Self = TypeVar("Self", bound="Foo") class Foo: def return_self(self: Self) -> Self: ... return self
通常,如果某個方法返回
self
,如上述示例所示,您應該使用Self
作為返回註解。如果Foo.return_self
被註解為返回"Foo"
,那麼型別檢查器將推斷SubclassOfFoo.return_self
返回的物件型別為Foo
而不是SubclassOfFoo
。其他常見用例包括
用作替代建構函式並返回
cls
引數例項的classmethod
。註解返回自身的
__enter__()
方法。
如果方法不保證在子類化時返回子類的例項,則不應使用
Self
作為返回註解。class Eggs: # Self would be an incorrect return annotation here, # as the object returned is always an instance of Eggs, # even in subclasses def returns_eggs(self) -> "Eggs": return Eggs()
有關更多詳細資訊,請參閱 PEP 673。
在 3.11 版本中新增。
- typing.TypeAlias¶
明確宣告類型別名的特殊註解。
例如:
from typing import TypeAlias Factors: TypeAlias = list[int]
TypeAlias
在較舊的 Python 版本上特別有用,用於註解使用前向引用的別名,因為型別檢查器很難將這些與普通變數賦值區分開來。from typing import Generic, TypeAlias, TypeVar T = TypeVar("T") # "Box" does not exist yet, # so we have to use quotes for the forward reference on Python <3.12. # Using ``TypeAlias`` tells the type checker that this is a type alias declaration, # not a variable assignment to a string. BoxOfStrings: TypeAlias = "Box[str]" class Box(Generic[T]): @classmethod def make_box_of_strings(cls) -> BoxOfStrings: ...
有關更多詳細資訊,請參閱 PEP 613。
在 3.10 版本加入。
自 3.12 版棄用:
TypeAlias
已棄用,取而代之的是type
語句,該語句建立TypeAliasType
的例項,並原生支援前向引用。請注意,雖然TypeAlias
和TypeAliasType
具有相似的用途和名稱,但它們是不同的,後者不是前者的型別。目前沒有計劃移除TypeAlias
,但建議使用者遷移到type
語句。
特殊形式¶
這些可用作註解中的型別。它們都支援使用 []
進行訂閱,但每個都具有獨特的語法。
- class typing.Union¶
聯合型別;
Union[X, Y]
等同於X | Y
,表示 X 或 Y。要定義聯合,請使用例如
Union[int, str]
或簡寫int | str
。建議使用簡寫。詳細資訊引數必須是型別,並且必須至少有一個。
聯合的聯合會被展平,例如
Union[Union[int, str], float] == Union[int, str, float]
但是,這不適用於透過類型別名引用的聯合,以避免強制評估底層
TypeAliasType
。type A = Union[int, str] Union[A, float] != Union[int, str, float]
單個引數的聯合會消失,例如
Union[int] == int # The constructor actually returns int
冗餘引數會被跳過,例如
Union[int, str, int] == Union[int, str] == int | str
比較聯合時,引數順序將被忽略,例如
Union[int, str] == Union[str, int]
您不能子類化或例項化
Union
。您不能寫入
Union[X][Y]
。
3.7 版本中的更改: 在執行時不從聯合中移除顯式子類。
3.10 版本中的更改: 聯合現在可以寫為
X | Y
。請參閱聯合型別表示式。3.14 版本中的更改:
types.UnionType
現在是Union
的別名,並且Union[int, str]
和int | str
都建立同一類的例項。要在執行時檢查物件是否為Union
,請使用isinstance(obj, Union)
。為了與 Python 的早期版本相容,請使用get_origin(obj) is typing.Union or get_origin(obj) is types.UnionType
。
- typing.Optional¶
Optional[X]
等同於X | None
(或Union[X, None]
)。請注意,這與可選引數的概念不同,可選引數是具有預設值的引數。具有預設值的可選引數不需要其型別註解上的
Optional
限定符,僅僅因為它可選。例如def foo(arg: int = 0) -> None: ...
另一方面,如果允許
None
的顯式值,則使用Optional
是合適的,無論引數是否可選。例如def foo(arg: Optional[int] = None) -> None: ...
3.10 版本中的更改: Optional 現在可以寫為
X | None
。請參閱聯合型別表示式。
- typing.Concatenate¶
用於註解高階函式的特殊形式。
Concatenate
可以與 Callable 和ParamSpec
結合使用,以註解一個新增、移除或轉換另一個可呼叫物件引數的高階可呼叫物件。用法形式為Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]
。Concatenate
目前僅在用作 Callable 的第一個引數時有效。Concatenate
的最後一個引數必須是ParamSpec
或省略號(...
)。例如,要註解一個裝飾器
with_lock
,它為被裝飾函式提供一個threading.Lock
,可以使用Concatenate
來指示with_lock
期望一個可呼叫物件,該物件以Lock
作為第一個引數,並返回一個具有不同型別簽名的可呼叫物件。在這種情況下,ParamSpec
表示返回的可呼叫物件的引數型別取決於傳入的可呼叫物件的引數型別。from collections.abc import Callable from threading import Lock from typing import Concatenate # Use this lock to ensure that only one thread is executing a function # at any time. my_lock = Lock() def with_lock[**P, R](f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]: '''A type-safe decorator which provides a lock.''' def inner(*args: P.args, **kwargs: P.kwargs) -> R: # Provide the lock as the first argument. return f(my_lock, *args, **kwargs) return inner @with_lock def sum_threadsafe(lock: Lock, numbers: list[float]) -> float: '''Add a list of numbers together in a thread-safe manner.''' with lock: return sum(numbers) # We don't need to pass in the lock ourselves thanks to the decorator. sum_threadsafe([1.1, 2.2, 3.3])
在 3.10 版本加入。
- typing.Literal¶
用於定義“字面量型別”的特殊型別形式。
Literal
可用於向型別檢查器指示註解物件的值等同於提供的字面量之一。例如:
def validate_simple(data: Any) -> Literal[True]: # always returns True ... type Mode = Literal['r', 'rb', 'w', 'wb'] def open_helper(file: str, mode: Mode) -> str: ... open_helper('/some/path', 'r') # Passes type check open_helper('/other/path', 'typo') # Error in type checker
Literal[...]
不能被子類化。在執行時,任意值都可以作為Literal[...]
的型別引數,但型別檢查器可能會施加限制。有關字面量型別的更多詳細資訊,請參閱 PEP 586。附加詳情
引數必須是字面量值,並且必須至少有一個。
巢狀的
Literal
型別會被展平,例如assert Literal[Literal[1, 2], 3] == Literal[1, 2, 3]
但是,這不適用於透過類型別名引用的
Literal
型別,以避免強制評估底層TypeAliasType
。type A = Literal[1, 2] assert Literal[A, 3] != Literal[1, 2, 3]
冗餘引數會被跳過,例如
assert Literal[1, 2, 1] == Literal[1, 2]
比較字面量時,引數順序將被忽略,例如
assert Literal[1, 2] == Literal[2, 1]
您不能子類化或例項化
Literal
。您不能寫入
Literal[X][Y]
。
在 3.8 版本加入。
- typing.ClassVar¶
用於標記類變數的特殊型別構造。
如 PEP 526 中所介紹,用 ClassVar 包裝的變數註解表示給定屬性旨在用作類變數,並且不應在類的例項上設定。用法
class Starship: stats: ClassVar[dict[str, int]] = {} # class variable damage: int = 10 # instance variable
ClassVar
只接受型別,不能進一步訂閱。ClassVar
本身不是一個類,不應與isinstance()
或issubclass()
一起使用。ClassVar
不會改變 Python 執行時行為,但可以被第三方型別檢查器使用。例如,型別檢查器可能會將以下程式碼標記為錯誤enterprise_d = Starship(3000) enterprise_d.stats = {} # Error, setting class variable on instance Starship.stats = {} # This is OK
3.5.3 版本新增。
- typing.Final¶
用於向型別檢查器指示最終名稱的特殊型別構造。
最終名稱不能在任何作用域中重新賦值。在類作用域中宣告的最終名稱不能在子類中被覆蓋。
例如:
MAX_SIZE: Final = 9000 MAX_SIZE += 1 # Error reported by type checker class Connection: TIMEOUT: Final[int] = 10 class FastConnector(Connection): TIMEOUT = 1 # Error reported by type checker
這些屬性沒有執行時檢查。有關更多詳細資訊,請參閱 PEP 591。
在 3.8 版本加入。
- typing.Required¶
用於將
TypedDict
鍵標記為必需的特殊型別構造。這主要用於
total=False
的 TypedDicts。有關更多詳細資訊,請參閱TypedDict
和 PEP 655。在 3.11 版本中新增。
- typing.ReadOnly¶
一個特殊的型別構造,用於將
TypedDict
的項標記為只讀。例如:
class Movie(TypedDict): title: ReadOnly[str] year: int def mutate_movie(m: Movie) -> None: m["year"] = 1999 # allowed m["title"] = "The Matrix" # typechecker error
此屬性沒有執行時檢查。
有關更多詳細資訊,請參閱
TypedDict
和 PEP 705。在 3.13 版本加入。
- typing.Annotated¶
用於向註解新增上下文特定元資料的特殊型別形式。
透過使用註解
Annotated[T, x]
將元資料x
新增到給定型別T
。使用Annotated
新增的元資料可用於靜態分析工具或在執行時。在執行時,元資料儲存在__metadata__
屬性中。如果庫或工具遇到註解
Annotated[T, x]
並且對元資料沒有特殊邏輯,它應該忽略元資料並簡單地將註解視為T
。因此,當代碼希望將註解用於 Python 靜態型別系統之外的目的時,Annotated
會很有用。使用
Annotated[T, x]
作為註解仍然允許對T
進行靜態型別檢查,因為型別檢查器將簡單地忽略元資料x
。透過這種方式,Annotated
與@no_type_check
裝飾器不同,後者也可以用於在型別系統範圍之外添加註解,但會完全停用函式或類的型別檢查。如何解釋元資料的責任在於遇到
Annotated
註解的工具或庫。遇到Annotated
型別的工具或庫可以掃描元資料元素以確定它們是否感興趣(例如,使用isinstance()
)。- Annotated[<type>, <metadata>]
這是一個示例,說明如何在進行範圍分析時使用
Annotated
向型別註解新增元資料。@dataclass class ValueRange: lo: int hi: int T1 = Annotated[int, ValueRange(-10, 5)] T2 = Annotated[T1, ValueRange(-20, 3)]
Annotated
的第一個引數必須是有效型別。可以提供多個元資料元素,因為Annotated
支援可變引數。元資料元素的順序會保留並影響相等性檢查。@dataclass class ctype: kind: str a1 = Annotated[int, ValueRange(3, 10), ctype("char")] a2 = Annotated[int, ctype("char"), ValueRange(3, 10)] assert a1 != a2 # Order matters
由使用註解的工具決定是否允許客戶端向一個註解新增多個元資料元素以及如何合併這些註解。
巢狀的
Annotated
型別會被展平。元資料元素的順序從最內層註解開始assert Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[ int, ValueRange(3, 10), ctype("char") ]
但是,這不適用於透過類型別名引用的
Annotated
型別,以避免強制評估底層TypeAliasType
。type From3To10[T] = Annotated[T, ValueRange(3, 10)] assert Annotated[From3To10[int], ctype("char")] != Annotated[ int, ValueRange(3, 10), ctype("char") ]
重複的元資料元素不會被移除。
assert Annotated[int, ValueRange(3, 10)] != Annotated[ int, ValueRange(3, 10), ValueRange(3, 10) ]
Annotated
可用於巢狀和泛型別名@dataclass class MaxLen: value: int type Vec[T] = Annotated[list[tuple[T, T]], MaxLen(10)] # When used in a type annotation, a type checker will treat "V" the same as # ``Annotated[list[tuple[int, int]], MaxLen(10)]``: type V = Vec[int]
Annotated
不能與解包的TypeVarTuple
一起使用type Variadic[*Ts] = Annotated[*Ts, Ann1] = Annotated[T1, T2, T3, ..., Ann1] # NOT valid
其中
T1
、T2
等是TypeVars
。這是無效的,因為只能向 Annotated 傳遞一個型別。預設情況下,
get_type_hints()
會從註解中去除元資料。傳入include_extras=True
以保留元資料。>>> from typing import Annotated, get_type_hints >>> def func(x: Annotated[int, "metadata"]) -> None: pass ... >>> get_type_hints(func) {'x': <class 'int'>, 'return': <class 'NoneType'>} >>> get_type_hints(func, include_extras=True) {'x': typing.Annotated[int, 'metadata'], 'return': <class 'NoneType'>}
在執行時,與
Annotated
型別關聯的元資料可以透過__metadata__
屬性檢索>>> from typing import Annotated >>> X = Annotated[int, "very", "important", "metadata"] >>> X typing.Annotated[int, 'very', 'important', 'metadata'] >>> X.__metadata__ ('very', 'important', 'metadata')
如果要檢索由
Annotated
包裝的原始型別,請使用__origin__
屬性>>> from typing import Annotated, get_origin >>> Password = Annotated[str, "secret"] >>> Password.__origin__ <class 'str'>
請注意,使用
get_origin()
將返回Annotated
本身。>>> get_origin(Password) typing.Annotated
參見
- PEP 593 - 靈活的函式和變數註解
PEP 將
Annotated
引入標準庫。
在 3.9 版本中新增。
- typing.TypeIs¶
用於標記使用者定義的型別謂詞函式的特殊型別構造。
TypeIs
可用於註解使用者定義的型別謂詞函式的返回型別。TypeIs
只接受一個型別引數。在執行時,以這種方式標記的函式應返回布林值並至少接受一個位置引數。TypeIs
旨在有利於 型別窄化 —— 靜態型別檢查器用來確定程式程式碼流中表達式更精確型別的一種技術。通常,型別窄化是透過分析條件程式碼流並將窄化應用於程式碼塊來完成的。這裡的條件表示式有時被稱為“型別謂詞”。def is_str(val: str | float): # "isinstance" type predicate if isinstance(val, str): # Type of ``val`` is narrowed to ``str`` ... else: # Else, type of ``val`` is narrowed to ``float``. ...
有時使用使用者定義的布林函式作為型別謂詞會很方便。這樣的函式應該使用
TypeIs[...]
或TypeGuard
作為其返回型別,以提醒靜態型別檢查器此意圖。TypeIs
通常比TypeGuard
具有更直觀的行為,但當輸入和輸出型別不相容(例如,list[object]
到list[int]
)或當函式不為窄化型別的所有例項返回True
時,它不能使用。使用
-> TypeIs[NarrowedType]
可以告訴靜態型別檢查器,對於給定函式其返回值是一個布林值。
如果返回值為
True
,則其引數的型別是引數原始型別和NarrowedType
的交集。如果返回值為
False
,則其引數的型別將被縮小以排除NarrowedType
。
例如:
from typing import assert_type, final, TypeIs class Parent: pass class Child(Parent): pass @final class Unrelated: pass def is_parent(val: object) -> TypeIs[Parent]: return isinstance(val, Parent) def run(arg: Child | Unrelated): if is_parent(arg): # Type of ``arg`` is narrowed to the intersection # of ``Parent`` and ``Child``, which is equivalent to # ``Child``. assert_type(arg, Child) else: # Type of ``arg`` is narrowed to exclude ``Parent``, # so only ``Unrelated`` is left. assert_type(arg, Unrelated)
TypeIs
中的型別必須與函式引數的型別一致;否則,靜態型別檢查器將引發錯誤。錯誤編寫的TypeIs
函式可能導致型別系統中的不健全行為;使用者有責任以型別安全的方式編寫此類函式。如果
TypeIs
函式是類或例項方法,則TypeIs
中的型別對映到第二個引數的型別(在cls
或self
之後)。簡而言之,形式為
def foo(arg: TypeA) -> TypeIs[TypeB]: ...
,意味著如果foo(arg)
返回True
,則arg
是TypeB
的一個例項;如果返回False
,則不是TypeB
的例項。TypeIs
也適用於型別變數。有關更多資訊,請參閱 PEP 742(使用TypeIs
縮小型別)。在 3.13 版本加入。
- typing.TypeGuard¶
用於標記使用者定義的型別謂詞函式的特殊型別構造。
型別謂詞函式是使用者定義的函式,用於返回其引數是否是特定型別的例項。
TypeGuard
的工作方式與TypeIs
類似,但對型別檢查行為有微妙的差異(見下文)。使用
-> TypeGuard
告訴靜態型別檢查器,對於給定函式其返回值是一個布林值。
如果返回值為
True
,則其引數的型別是TypeGuard
中的型別。
TypeGuard
也適用於型別變數。有關更多詳細資訊,請參閱 PEP 647。例如:
def is_str_list(val: list[object]) -> TypeGuard[list[str]]: '''Determines whether all objects in the list are strings''' return all(isinstance(x, str) for x in val) def func1(val: list[object]): if is_str_list(val): # Type of ``val`` is narrowed to ``list[str]``. print(" ".join(val)) else: # Type of ``val`` remains as ``list[object]``. print("Not a list of strings!")
TypeIs
和TypeGuard
的區別如下TypeIs
要求縮小後的型別是輸入型別的子型別,而TypeGuard
則不要求。主要原因是允許將list[object]
縮小為list[str]
之類的情況,儘管後者不是前者的子型別,因為list
是不變的。當
TypeGuard
函式返回True
時,型別檢查器將變數的型別精確地縮小為TypeGuard
型別。當TypeIs
函式返回True
時,型別檢查器可以推斷出更精確的型別,將變數先前已知的型別與TypeIs
型別結合起來。(從技術上講,這被稱為交集型別。)當
TypeGuard
函式返回False
時,型別檢查器根本無法縮小變數的型別。當TypeIs
函式返回False
時,型別檢查器可以將變數的型別縮小以排除TypeIs
型別。
在 3.10 版本加入。
- typing.Unpack¶
型別運算子,用於概念上標記一個物件已被解包。
例如,在 型別變數元組 上使用解包運算子
*
等同於使用Unpack
將型別變數元組標記為已解包Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Effectively does: tup: tuple[Unpack[Ts]]
實際上,在
typing.TypeVarTuple
和builtins.tuple
型別的上下文中,Unpack
可以與*
互換使用。在較舊的 Python 版本中,你可能會看到Unpack
被顯式使用,因為*
無法在某些地方使用# In older versions of Python, TypeVarTuple and Unpack # are located in the `typing_extensions` backports package. from typing_extensions import TypeVarTuple, Unpack Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Syntax error on Python <= 3.10! tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatible
Unpack
還可以與typing.TypedDict
一起用於在函式簽名中為**kwargs
鍵入型別from typing import TypedDict, Unpack class Movie(TypedDict): name: str year: int # This function expects two keyword arguments - `name` of type `str` # and `year` of type `int`. def foo(**kwargs: Unpack[Movie]): ...
有關使用
Unpack
進行**kwargs
型別鍵入的更多詳細資訊,請參閱 PEP 692。在 3.11 版本中新增。
構建泛型型別和類型別名¶
以下類不應直接用作註解。它們旨在作為建立泛型型別和類型別名的構建塊。
這些物件可以透過特殊語法(型別引數列表 和 type
語句)建立。為了與 Python 3.11 及更早版本相容,它們也可以不使用專用語法建立,如下所述。
- class typing.Generic¶
泛型型別的抽象基類。
泛型型別通常透過在類名後新增型別引數列表來宣告
class Mapping[KT, VT]: def __getitem__(self, key: KT) -> VT: ... # Etc.
這樣的類隱式地繼承自
Generic
。此語法的執行時語義在 語言參考 中討論。然後可以如下使用此類
def lookup_name[X, Y](mapping: Mapping[X, Y], key: X, default: Y) -> Y: try: return mapping[key] except KeyError: return default
此處函式名後面的括號表示一個 泛型函式。
為了向後相容,泛型類也可以透過顯式繼承自
Generic
來宣告。在這種情況下,型別引數必須單獨宣告KT = TypeVar('KT') VT = TypeVar('VT') class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc.
- class typing.TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault)¶
型別變數。
構造型別變數的首選方式是透過 泛型函式、泛型類 和 泛型類型別名 的專用語法
class Sequence[T]: # T is a TypeVar ...
此語法還可用於建立有界和受約束的型別變數
class StrSequence[S: str]: # S is a TypeVar with a `str` upper bound; ... # we can say that S is "bounded by `str`" class StrOrBytesSequence[A: (str, bytes)]: # A is a TypeVar constrained to str or bytes ...
但是,如果需要,可重用型別變數也可以手動構造,如下所示
T = TypeVar('T') # Can be anything S = TypeVar('S', bound=str) # Can be any subtype of str A = TypeVar('A', str, bytes) # Must be exactly str or bytes
型別變數主要用於靜態型別檢查器。它們作為泛型型別以及泛型函式和類型別名定義的引數。有關泛型型別的更多資訊,請參閱
Generic
。泛型函式的工作原理如下def repeat[T](x: T, n: int) -> Sequence[T]: """Return a list containing n references to x.""" return [x]*n def print_capitalized[S: str](x: S) -> S: """Print x capitalized, and return x.""" print(x.capitalize()) return x def concatenate[A: (str, bytes)](x: A, y: A) -> A: """Add two strings or bytes objects together.""" return x + y
請注意,型別變數可以是 *有界的*、*受約束的*,或兩者都不是,但不能同時是有界的 *和* 受約束的。
型別變數的方差由型別檢查器在透過 型別引數語法 建立時,或傳入
infer_variance=True
時推斷。手動建立的型別變數可以透過傳入covariant=True
或contravariant=True
顯式標記為協變或逆變。預設情況下,手動建立的型別變數是不變的。有關更多詳細資訊,請參閱 PEP 484 和 PEP 695。有界型別變數和受約束型別變數在幾個重要方面具有不同的語義。使用 *有界* 型別變數意味著
TypeVar
將使用最具體的型別求解x = print_capitalized('a string') reveal_type(x) # revealed type is str class StringSubclass(str): pass y = print_capitalized(StringSubclass('another string')) reveal_type(y) # revealed type is StringSubclass z = print_capitalized(45) # error: int is not a subtype of str
型別變數的上限可以是具體型別、抽象型別(ABC 或 Protocol),甚至是型別聯合
# Can be anything with an __abs__ method def print_abs[T: SupportsAbs](arg: T) -> None: print("Absolute value:", abs(arg)) U = TypeVar('U', bound=str|bytes) # Can be any subtype of the union str|bytes V = TypeVar('V', bound=SupportsAbs) # Can be anything with an __abs__ method
然而,使用 *受約束* 型別變數意味著
TypeVar
只能被求解為正好是給定約束之一a = concatenate('one', 'two') reveal_type(a) # revealed type is str b = concatenate(StringSubclass('one'), StringSubclass('two')) reveal_type(b) # revealed type is str, despite StringSubclass being passed in c = concatenate('one', b'two') # error: type variable 'A' can be either str or bytes in a function call, but not both
在執行時,
isinstance(x, T)
將引發TypeError
。- __name__¶
型別變數的名稱。
- __covariant__¶
型別變數是否已顯式標記為協變。
- __contravariant__¶
型別變數是否已顯式標記為逆變。
- __infer_variance__¶
型別檢查器是否應推斷型別變數的方差。
3.12 新版功能.
- __bound__¶
型別變數的上限(如果有)。
- evaluate_bound()¶
一個 評估函式,對應於
__bound__
屬性。直接呼叫時,此方法僅支援VALUE
格式,這等同於直接訪問__bound__
屬性,但方法物件可以傳遞給annotationlib.call_evaluate_function()
以不同格式評估值。在 3.14 版本加入。
- __constraints__¶
包含型別變數約束的元組(如果有)。
- evaluate_constraints()¶
一個 評估函式,對應於
__constraints__
屬性。直接呼叫時,此方法僅支援VALUE
格式,這等同於直接訪問__constraints__
屬性,但方法物件可以傳遞給annotationlib.call_evaluate_function()
以不同格式評估值。在 3.14 版本加入。
- __default__¶
型別變數的預設值,如果沒有預設值,則為
typing.NoDefault
。在 3.13 版本加入。
- evaluate_default()¶
一個 評估函式,對應於
__default__
屬性。直接呼叫時,此方法僅支援VALUE
格式,這等同於直接訪問__default__
屬性,但方法物件可以傳遞給annotationlib.call_evaluate_function()
以不同格式評估值。在 3.14 版本加入。
- has_default()¶
返回型別變數是否具有預設值。這等同於檢查
__default__
是否不是typing.NoDefault
單例,只是它不會強制評估 惰性評估 的預設值。在 3.13 版本加入。
3.13 版本中的變化: 添加了對預設值的支援。
- class typing.TypeVarTuple(name, *, default=typing.NoDefault)¶
型別變數元組。型別變數 的一種特殊形式,支援 *可變引數* 泛型。
型別變數元組可以在 型別引數列表 中使用名稱前的一個星號 (
*
) 宣告def move_first_element_to_last[T, *Ts](tup: tuple[T, *Ts]) -> tuple[*Ts, T]: return (*tup[1:], tup[0])
或者透過顯式呼叫
TypeVarTuple
建構函式T = TypeVar("T") Ts = TypeVarTuple("Ts") def move_first_element_to_last(tup: tuple[T, *Ts]) -> tuple[*Ts, T]: return (*tup[1:], tup[0])
普通型別變數允許使用單一型別進行引數化。相比之下,型別變數元組透過像元組中包含任意數量的型別變數一樣,允許使用 *任意* 數量的型別進行引數化。例如
# T is bound to int, Ts is bound to () # Return value is (1,), which has type tuple[int] move_first_element_to_last(tup=(1,)) # T is bound to int, Ts is bound to (str,) # Return value is ('spam', 1), which has type tuple[str, int] move_first_element_to_last(tup=(1, 'spam')) # T is bound to int, Ts is bound to (str, float) # Return value is ('spam', 3.0, 1), which has type tuple[str, float, int] move_first_element_to_last(tup=(1, 'spam', 3.0)) # This fails to type check (and fails at runtime) # because tuple[()] is not compatible with tuple[T, *Ts] # (at least one element is required) move_first_element_to_last(tup=())
注意
tuple[T, *Ts]
中解包運算子*
的使用。概念上,你可以將Ts
視為一個型別變數元組(T1, T2, ...)
。tuple[T, *Ts]
將變為tuple[T, *(T1, T2, ...)]
,這等同於tuple[T, T1, T2, ...]
。(請注意,在較舊的 Python 版本中,你可能會看到使用Unpack
來編寫,例如Unpack[Ts]
。)型別變數元組必須 *始終* 被解包。這有助於將型別變數元組與普通型別變數區分開來
x: Ts # Not valid x: tuple[Ts] # Not valid x: tuple[*Ts] # The correct way to do it
型別變數元組可以在與普通型別變數相同的上下文中使用。例如,在類定義、引數和返回型別中
class Array[*Shape]: def __getitem__(self, key: tuple[*Shape]) -> float: ... def __abs__(self) -> "Array[*Shape]": ... def get_shape(self) -> tuple[*Shape]: ...
型別變數元組可以與普通型別變數很好地結合使用
class Array[DType, *Shape]: # This is fine pass class Array2[*Shape, DType]: # This would also be fine pass class Height: ... class Width: ... float_array_1d: Array[float, Height] = Array() # Totally fine int_array_2d: Array[int, Height, Width] = Array() # Yup, fine too
但是,請注意,在單個型別引數列表或型別引數列表中最多隻能出現一個型別變數元組
x: tuple[*Ts, *Ts] # Not valid class Array[*Shape, *Shape]: # Not valid pass
最後,解包的型別變數元組可以用作
*args
的型別註解def call_soon[*Ts]( callback: Callable[[*Ts], None], *args: *Ts ) -> None: ... callback(*args)
與
*args
的未解包註解(例如*args: int
,這將指定 *所有* 引數都是int
)相反,*args: *Ts
允許引用*args
中 *單個* 引數的型別。在這裡,這允許我們確保傳遞給call_soon
的*args
的型別與callback
的(位置)引數的型別匹配。有關型別變數元組的更多詳細資訊,請參閱 PEP 646。
- __name__¶
型別變數元組的名稱。
- __default__¶
型別變數元組的預設值,如果沒有預設值,則為
typing.NoDefault
。在 3.13 版本加入。
- evaluate_default()¶
一個 評估函式,對應於
__default__
屬性。直接呼叫時,此方法僅支援VALUE
格式,這等同於直接訪問__default__
屬性,但方法物件可以傳遞給annotationlib.call_evaluate_function()
以不同格式評估值。在 3.14 版本加入。
- has_default()¶
返回型別變數元組是否具有預設值。這等同於檢查
__default__
是否不是typing.NoDefault
單例,只是它不會強制評估 惰性評估 的預設值。在 3.13 版本加入。
在 3.11 版本中新增。
3.13 版本中的變化: 添加了對預設值的支援。
- class typing.ParamSpec(name, *, bound=None, covariant=False, contravariant=False, default=typing.NoDefault)¶
引數規範變數。型別變數 的一種特殊版本。
在 型別引數列表 中,引數規範可以用兩個星號 (
**
) 宣告type IntFunc[**P] = Callable[P, int]
為了與 Python 3.11 及更早版本相容,
ParamSpec
物件也可以按如下方式建立P = ParamSpec('P')
引數規範變數主要用於靜態型別檢查器。它們用於將一個可呼叫物件的引數型別轉發到另一個可呼叫物件——這種模式常見於高階函式和裝飾器中。它們僅在
Concatenate
中,或作為Callable
的第一個引數,或作為使用者定義泛型的引數時有效。有關泛型型別的更多資訊,請參閱Generic
。例如,要為函式新增基本日誌記錄,可以建立一個裝飾器
add_logging
來記錄函式呼叫。引數規範變數告訴型別檢查器,傳入裝飾器的可呼叫物件和它返回的新可呼叫物件具有相互依賴的型別引數from collections.abc import Callable import logging def add_logging[T, **P](f: Callable[P, T]) -> Callable[P, T]: '''A type-safe decorator to add logging to a function.''' def inner(*args: P.args, **kwargs: P.kwargs) -> T: logging.info(f'{f.__name__} was called') return f(*args, **kwargs) return inner @add_logging def add_two(x: float, y: float) -> float: '''Add two numbers together.''' return x + y
如果沒有
ParamSpec
,之前標註此函式的最簡單方法是使用一個上限為Callable[..., Any]
的TypeVar
。但這會導致兩個問題型別檢查器無法型別檢查
inner
函式,因為*args
和**kwargs
必須被型別化為Any
。在返回
inner
函式時,可能需要在add_logging
裝飾器的主體中使用cast()
,或者必須告知靜態型別檢查器忽略return inner
。
- args¶
- kwargs¶
由於
ParamSpec
捕獲位置引數和關鍵字引數,因此可以使用P.args
和P.kwargs
將ParamSpec
拆分為其元件。P.args
表示給定呼叫中的位置引數元組,並且應僅用於註解*args
。P.kwargs
表示給定呼叫中關鍵字引數到其值的對映,並且應僅用於註解**kwargs
。這兩個屬性都要求註解的引數在作用域內。在執行時,P.args
和P.kwargs
分別是ParamSpecArgs
和ParamSpecKwargs
的例項。
- __name__¶
引數規範的名稱。
- __default__¶
引數規範的預設值,如果沒有預設值,則為
typing.NoDefault
。在 3.13 版本加入。
- evaluate_default()¶
一個 評估函式,對應於
__default__
屬性。直接呼叫時,此方法僅支援VALUE
格式,這等同於直接訪問__default__
屬性,但方法物件可以傳遞給annotationlib.call_evaluate_function()
以不同格式評估值。在 3.14 版本加入。
- has_default()¶
返回引數規範是否具有預設值。這等同於檢查
__default__
是否不是typing.NoDefault
單例,只是它不會強制評估 惰性評估 的預設值。在 3.13 版本加入。
使用
covariant=True
或contravariant=True
建立的引數規範變數可用於宣告協變或逆變泛型型別。bound
引數也接受,類似於TypeVar
。但是,這些關鍵字的實際語義尚待確定。在 3.10 版本加入。
3.13 版本中的變化: 添加了對預設值的支援。
備註
只有在全域性作用域中定義的引數規範變數才能被 pickle。
參見
PEP 612 – 引數規範變數(引入
ParamSpec
和Concatenate
的 PEP)
- typing.ParamSpecArgs¶
- typing.ParamSpecKwargs¶
ParamSpec
的引數和關鍵字引數屬性。ParamSpec
的P.args
屬性是ParamSpecArgs
的例項,而P.kwargs
是ParamSpecKwargs
的例項。它們旨在用於執行時內省,對靜態型別檢查器沒有特殊含義。對這些物件中的任何一個呼叫
get_origin()
將返回原始的ParamSpec
>>> from typing import ParamSpec, get_origin >>> P = ParamSpec("P") >>> get_origin(P.args) is P True >>> get_origin(P.kwargs) is P True
在 3.10 版本加入。
- class typing.TypeAliasType(name, value, *, type_params=())¶
透過
type
語句建立的類型別名的型別。示例
>>> type Alias = int >>> type(Alias) <class 'typing.TypeAliasType'>
3.12 新版功能.
- __name__¶
類型別名的名稱
>>> type Alias = int >>> Alias.__name__ 'Alias'
- __module__¶
定義類型別名的模組名稱
>>> type Alias = int >>> Alias.__module__ '__main__'
- __type_params__¶
類型別名的型別引數,如果別名不是泛型的,則為空元組
>>> type ListOrSet[T] = list[T] | set[T] >>> ListOrSet.__type_params__ (T,) >>> type NotGeneric = int >>> NotGeneric.__type_params__ ()
- __value__¶
類型別名的值。這是 惰性評估 的,因此別名定義中使用的名稱直到訪問
__value__
屬性時才會被解析>>> type Mutually = Recursive >>> type Recursive = Mutually >>> Mutually Mutually >>> Recursive Recursive >>> Mutually.__value__ Recursive >>> Recursive.__value__ Mutually
- evaluate_value()¶
一個 評估函式,對應於
__value__
屬性。直接呼叫時,此方法僅支援VALUE
格式,這等同於直接訪問__value__
屬性,但方法物件可以傳遞給annotationlib.call_evaluate_function()
以不同格式評估值>>> type Alias = undefined >>> Alias.__value__ Traceback (most recent call last): ... NameError: name 'undefined' is not defined >>> from annotationlib import Format, call_evaluate_function >>> Alias.evaluate_value(Format.VALUE) Traceback (most recent call last): ... NameError: name 'undefined' is not defined >>> call_evaluate_function(Alias.evaluate_value, Format.FORWARDREF) ForwardRef('undefined')
在 3.14 版本加入。
解包
類型別名支援使用
*Alias
語法進行星號解包。這等同於直接使用Unpack[Alias]
>>> type Alias = tuple[int, str] >>> type Unpacked = tuple[bool, *Alias] >>> Unpacked.__value__ tuple[bool, typing.Unpack[Alias]]
在 3.14 版本加入。
其他特殊指令¶
這些函式和類不應直接用作註解。它們旨在作為建立和宣告型別的構建塊。
- class typing.NamedTuple¶
collections.namedtuple()
的帶型別版本。用法
class Employee(NamedTuple): name: str id: int
這等價於:
Employee = collections.namedtuple('Employee', ['name', 'id'])
要為欄位提供預設值,可以在類主體中為其賦值
class Employee(NamedTuple): name: str id: int = 3 employee = Employee('Guido') assert employee.id == 3
具有預設值的欄位必須位於任何沒有預設值的欄位之後。
生成的類有一個額外的屬性
__annotations__
,它給出了一個將欄位名稱對映到欄位型別的字典。(欄位名稱在_fields
屬性中,預設值在_field_defaults
屬性中,這兩個屬性都是namedtuple()
API 的一部分。)NamedTuple
子類還可以有文件字串和方法class Employee(NamedTuple): """Represents an employee.""" name: str id: int = 3 def __repr__(self) -> str: return f'<Employee {self.name}, id={self.id}>'
NamedTuple
子類可以是泛型的class Group[T](NamedTuple): key: T group: list[T]
向後相容用法
# For creating a generic NamedTuple on Python 3.11 T = TypeVar("T") class Group(NamedTuple, Generic[T]): key: T group: list[T] # A functional syntax is also supported Employee = NamedTuple('Employee', [('name', str), ('id', int)])
3.6 版本中的變化: 添加了對 PEP 526 變數註解語法的支援。
3.6.1 版本中的變化: 添加了對預設值、方法和文件字串的支援。
3.8 版本中的變化:
_field_types
和__annotations__
屬性現在是普通字典而不是OrderedDict
的例項。3.9 版本中的變化: 刪除了
_field_types
屬性,取而代之的是更標準的__annotations__
屬性,它包含相同的資訊。3.11 版本中的變化: 添加了對泛型命名元組的支援。
自 3.13 版棄用,將在 3.15 版中移除: 用於建立 NamedTuple 類的未文件關鍵字引數語法 (
NT = NamedTuple("NT", x=int)
) 已棄用,並將在 3.15 中停用。請改用基於類或函式式語法。自 3.13 版棄用,將在 3.15 版中移除: 在使用函式式語法建立 NamedTuple 類時,未向“fields”引數傳遞值 (
NT = NamedTuple("NT")
) 已棄用。向“fields”引數傳遞None
(NT = NamedTuple("NT", None)
) 也已棄用。兩者都將在 Python 3.15 中停用。要建立具有 0 個欄位的 NamedTuple 類,請使用class NT(NamedTuple): pass
或NT = NamedTuple("NT", [])
。
- class typing.NewType(name, tp)¶
用於建立低開銷 不同型別 的輔助類。
NewType
被型別檢查器視為一種不同的型別。然而,在執行時,呼叫NewType
會返回其引數不變。用法
UserId = NewType('UserId', int) # Declare the NewType "UserId" first_user = UserId(1) # "UserId" returns the argument unchanged at runtime
- __module__¶
定義新型別的模組的名稱。
- __name__¶
新型別的名稱。
- __supertype__¶
新型別所基於的型別。
3.5.2 版本新增。
3.10 版本中的變化:
NewType
現在是一個類而不是一個函式。
- class typing.Protocol(Generic)¶
協議類的基類。
協議類定義如下
class Proto(Protocol): def meth(self) -> int: ...
此類主要與識別結構子型別(靜態鴨子型別)的靜態型別檢查器一起使用,例如
class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check
有關更多詳細資訊,請參閱 PEP 544。用
runtime_checkable()
(稍後描述)裝飾的協議類充當簡單的執行時協議,僅檢查給定屬性的存在,而忽略其型別簽名。沒有此裝飾器的協議類不能用作isinstance()
或issubclass()
的第二個引數。協議類可以是泛型的,例如
class GenProto[T](Protocol): def meth(self) -> T: ...
在需要與 Python 3.11 或更早版本相容的程式碼中,泛型協議可以按如下方式編寫
T = TypeVar("T") class GenProto(Protocol[T]): def meth(self) -> T: ...
在 3.8 版本加入。
- @typing.runtime_checkable¶
將協議類標記為執行時協議。
此協議可與
isinstance()
和issubclass()
一起使用。這允許進行簡單的結構檢查,這與collections.abc
中的“一招鮮”類似,例如Iterable
。例如@runtime_checkable class Closable(Protocol): def close(self): ... assert isinstance(open('/some/file'), Closable) @runtime_checkable class Named(Protocol): name: str import threading assert isinstance(threading.Thread(name='Bob'), Named)
當應用於非協議類時,此裝飾器會引發
TypeError
。備註
runtime_checkable()
將僅檢查所需方法或屬性的存在,而不檢查它們的型別簽名或型別。例如,ssl.SSLObject
是一個類,因此它通過了issubclass()
對 Callable 的檢查。但是,ssl.SSLObject.__init__
方法僅用於引發帶有更具資訊性訊息的TypeError
,因此無法呼叫(例項化)ssl.SSLObject
。備註
與對非協議類的
isinstance()
檢查相比,對執行時可檢查協議的isinstance()
檢查可能會出乎意料地慢。在效能敏感的程式碼中,請考慮使用hasattr()
呼叫等替代方案進行結構檢查。在 3.8 版本加入。
3.12 版本中的變化: 針對執行時可檢查協議的
isinstance()
檢查的內部實現現在使用inspect.getattr_static()
來查詢屬性(以前使用hasattr()
)。因此,在 Python 3.12+ 上,某些過去被認為是執行時可檢查協議例項的物件可能不再被認為是該協議的例項,反之亦然。大多數使用者不太可能受到此更改的影響。3.12 版本中的變化: 執行時可檢查協議的成員現在在類建立後立即在執行時被視為“凍結”。修補執行時可檢查協議的屬性仍然有效,但不會對比較物件與協議的
isinstance()
檢查產生影響。有關更多詳細資訊,請參閱 Python 3.12 中的新特性。
- class typing.TypedDict(dict)¶
用於為字典新增型別提示的特殊構造。在執行時,它是一個普通的
dict
。TypedDict
聲明瞭一個字典型別,它期望其所有例項都具有一組特定的鍵,其中每個鍵都與一致型別的值相關聯。這種期望在執行時不會被檢查,僅由型別檢查器強制執行。用法class Point2D(TypedDict): x: int y: int label: str a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')
建立
TypedDict
的另一種方法是使用函式呼叫語法。第二個引數必須是一個字面dict
Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})
此函式式語法允許定義非有效 識別符號 的鍵,例如因為它們是關鍵字或包含連字元,或者當鍵名不能像常規私有名稱一樣被 損壞 時
# raises SyntaxError class Point2D(TypedDict): in: int # 'in' is a keyword x-y: int # name with hyphens class Definition(TypedDict): __schema: str # mangled to `_Definition__schema` # OK, functional syntax Point2D = TypedDict('Point2D', {'in': int, 'x-y': int}) Definition = TypedDict('Definition', {'__schema': str}) # not mangled
預設情況下,所有鍵都必須存在於
TypedDict
中。可以使用NotRequired
將單個鍵標記為非必需class Point2D(TypedDict): x: int y: int label: NotRequired[str] # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': NotRequired[str]})
這意味著
Point2D
TypedDict
可以省略label
鍵。也可以透過指定
False
的總量來預設將所有鍵標記為非必需class Point2D(TypedDict, total=False): x: int y: int # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)
這意味著
Point2D
TypedDict
可以省略任何鍵。型別檢查器僅期望支援字面值False
或True
作為total
引數的值。True
是預設值,並使類主體中定義的所有項成為必需項。total=False
TypedDict
的單個鍵可以使用Required
標記為必需class Point2D(TypedDict, total=False): x: Required[int] y: Required[int] label: str # Alternative syntax Point2D = TypedDict('Point2D', { 'x': Required[int], 'y': Required[int], 'label': str }, total=False)
TypedDict
型別可以使用基於類的語法繼承一個或多個其他TypedDict
型別。用法class Point3D(Point2D): z: int
Point3D
有三個項:x
、y
和z
。這等同於此定義class Point3D(TypedDict): x: int y: int z: int
一個
TypedDict
不能從非TypedDict
類繼承,除了Generic
。例如class X(TypedDict): x: int class Y(TypedDict): y: int class Z(object): pass # A non-TypedDict class class XY(X, Y): pass # OK class XZ(X, Z): pass # raises TypeError
一個
TypedDict
可以是泛型的class Group[T](TypedDict): key: T group: list[T]
要建立與 Python 3.11 或更低版本相容的泛型
TypedDict
,請顯式繼承自Generic
T = TypeVar("T") class Group(TypedDict, Generic[T]): key: T group: list[T]
TypedDict
可以透過註解字典(有關注解最佳實踐的更多資訊,請參閱 註解最佳實踐)、__total__
、__required_keys__
和__optional_keys__
進行內省。- __total__¶
Point2D.__total__
給出total
引數的值。示例>>> from typing import TypedDict >>> class Point2D(TypedDict): pass >>> Point2D.__total__ True >>> class Point2D(TypedDict, total=False): pass >>> Point2D.__total__ False >>> class Point3D(Point2D): pass >>> Point3D.__total__ True
此屬性 *僅* 反映當前
TypedDict
類的total
引數值,而不是該類是否在語義上是完整的。例如,一個__total__
設定為True
的TypedDict
可能具有用NotRequired
標記的鍵,或者它可能繼承自另一個TypedDict
,其total=False
。因此,通常最好使用__required_keys__
和__optional_keys__
進行內省。
- __required_keys__¶
在 3.9 版本中新增。
- __optional_keys__¶
Point2D.__required_keys__
和Point2D.__optional_keys__
分別返回包含必需鍵和非必需鍵的frozenset
物件。標記為
Required
的鍵將始終出現在__required_keys__
中,標記為NotRequired
的鍵將始終出現在__optional_keys__
中。為了向後相容 Python 3.10 及更早版本,還可以使用繼承在同一個
TypedDict
中同時宣告必需鍵和非必需鍵。這透過宣告一個TypedDict
,其total
引數有一個值,然後在其另一個TypedDict
中繼承它,該TypedDict
的total
具有不同的值>>> class Point2D(TypedDict, total=False): ... x: int ... y: int ... >>> class Point3D(Point2D): ... z: int ... >>> Point3D.__required_keys__ == frozenset({'z'}) True >>> Point3D.__optional_keys__ == frozenset({'x', 'y'}) True
在 3.9 版本中新增。
備註
如果使用
from __future__ import annotations
或將註解作為字串提供,則在定義TypedDict
時不會評估註解。因此,__required_keys__
和__optional_keys__
依賴的執行時內省可能無法正常工作,並且屬性值可能不正確。
對
ReadOnly
的支援反映在以下屬性中有關更多示例和詳細規則,請參閱型別文件中的 TypedDict 部分。
在 3.8 版本加入。
3.11 版本中的變化: 添加了對將單個鍵標記為
Required
或NotRequired
的支援。請參閱 PEP 655。版本 3.11 中的變化: 添加了對泛型
TypedDict
的支援。版本 3.13 中的變化: 移除了透過關鍵字引數方法建立
TypedDict
的支援。版本 3.13 中的變化: 添加了對
ReadOnly
限定符的支援。自 3.13 版本棄用,將在 3.15 版本中移除: 當使用函式式語法建立 TypedDict 類時,未能向 'fields' 引數傳遞值 (
TD = TypedDict("TD")
) 已被棄用。向 'fields' 引數傳遞None
(TD = TypedDict("TD", None)
) 也已被棄用。兩者都將在 Python 3.15 中被禁止。要建立一個包含 0 個欄位的 TypedDict 類,請使用class TD(TypedDict): pass
或TD = TypedDict("TD", {})
。
協議¶
typing
模組提供了以下協議。所有協議都用 @runtime_checkable
裝飾。
- class typing.SupportsAbs¶
一個 ABC,帶有一個抽象方法
__abs__
,其返回型別是協變的。
- class typing.SupportsBytes¶
一個 ABC,帶有一個抽象方法
__bytes__
。
- class typing.SupportsComplex¶
一個 ABC,帶有一個抽象方法
__complex__
。
- class typing.SupportsFloat¶
一個 ABC,帶有一個抽象方法
__float__
。
- class typing.SupportsIndex¶
一個 ABC,帶有一個抽象方法
__index__
。在 3.8 版本加入。
- class typing.SupportsInt¶
一個 ABC,帶有一個抽象方法
__int__
。
- class typing.SupportsRound¶
一個 ABC,帶有一個抽象方法
__round__
,其返回型別是協變的。
用於處理 I/O 的 ABC 和協議¶
- class typing.IO[AnyStr]¶
- class typing.TextIO[AnyStr]¶
- class typing.BinaryIO[AnyStr]¶
泛型類
IO[AnyStr]
及其子類TextIO(IO[str])
和BinaryIO(IO[bytes])
表示 I/O 流的型別,例如由open()
返回的流。請注意,這些類不是協議,它們的介面相當廣泛。
協議 io.Reader
和 io.Writer
為引數型別提供了更簡單的替代方案,分別僅在訪問 read()
或 write()
方法時使用
def read_and_write(reader: Reader[str], writer: Writer[bytes]):
data = reader.read()
writer.write(data.encode())
還可以考慮使用 collections.abc.Iterable
來迭代輸入流的行
def read_config(stream: Iterable[str]):
for line in stream:
...
函式和裝飾器¶
- typing.cast(typ, val)¶
將值強制轉換為某種型別。
這會原樣返回該值。對於型別檢查器來說,這表示返回值具有指定的型別,但在執行時我們有意不檢查任何內容(我們希望它儘可能快)。
- typing.assert_type(val, typ, /)¶
要求靜態型別檢查器確認 val 的推斷型別為 typ。
在執行時,這不做任何事情:它返回第一個引數不變,沒有檢查或副作用,無論引數的實際型別是什麼。
當靜態型別檢查器遇到對
assert_type()
的呼叫時,如果值不是指定型別,它會發出錯誤def greet(name: str) -> None: assert_type(name, str) # OK, inferred type of `name` is `str` assert_type(name, int) # type checker error
此函式有助於確保型別檢查器對指令碼的理解與開發者的意圖一致
def complex_function(arg: object): # Do some complex type-narrowing logic, # after which we hope the inferred type will be `int` ... # Test whether the type checker correctly understands our function assert_type(arg, int)
在 3.11 版本中新增。
- typing.assert_never(arg, /)¶
要求靜態型別檢查器確認某行程式碼無法訪問。
示例
def int_or_str(arg: int | str) -> None: match arg: case int(): print("It's an int") case str(): print("It's a str") case _ as unreachable: assert_never(unreachable)
在這裡,註解允許型別檢查器推斷出最後一個 case 永遠不會執行,因為
arg
要麼是int
要麼是str
,並且這兩個選項都被前面的 case 覆蓋了。如果型別檢查器發現對
assert_never()
的呼叫是可達的,它將發出錯誤。例如,如果arg
的型別註解是int | str | float
,則型別檢查器將發出錯誤,指出unreachable
的型別是float
。要使對assert_never
的呼叫透過型別檢查,傳入引數的推斷型別必須是底部型別Never
,而不是其他任何型別。在執行時,當呼叫此函式時會引發異常。
參見
不可達程式碼和窮盡性檢查 提供了有關使用靜態型別進行窮盡性檢查的更多資訊。
在 3.11 版本中新增。
- typing.reveal_type(obj, /)¶
要求靜態型別檢查器顯示錶達式的推斷型別。
當靜態型別檢查器遇到對此函式的呼叫時,它會發出一個帶有引數推斷型別的診斷。例如
x: int = 1 reveal_type(x) # Revealed type is "builtins.int"
當您想除錯型別檢查器如何處理特定程式碼時,這會很有用。
在執行時,此函式將其引數的執行時型別列印到
sys.stderr
並原樣返回引數(允許在表示式中使用該呼叫)x = reveal_type(1) # prints "Runtime type is int" print(x) # prints "1"
請注意,執行時型別可能與(更具體或不那麼具體於)型別檢查器靜態推斷的型別不同。
大多數型別檢查器都支援在任何地方使用
reveal_type()
,即使該名稱沒有從typing
匯入。然而,從typing
匯入該名稱可以使您的程式碼在執行時不會出現錯誤,並更清楚地傳達意圖。在 3.11 版本中新增。
- @typing.dataclass_transform(*, eq_default=True, order_default=False, kw_only_default=False, frozen_default=False, field_specifiers=(), **kwargs)¶
標記物件提供
dataclass
-like 行為的裝飾器。dataclass_transform
可用於裝飾類、元類或本身是裝飾器的函式。@dataclass_transform()
的存在告訴靜態型別檢查器,被裝飾物件執行執行時“魔術”,以類似於@dataclasses.dataclass
的方式轉換類。裝飾器函式的使用示例
@dataclass_transform() def create_model[T](cls: type[T]) -> type[T]: ... return cls @create_model class CustomerModel: id: int name: str
在基類上
@dataclass_transform() class ModelBase: ... class CustomerModel(ModelBase): id: int name: str
在元類上
@dataclass_transform() class ModelMeta(type): ... class ModelBase(metaclass=ModelMeta): ... class CustomerModel(ModelBase): id: int name: str
上面定義的
CustomerModel
類將被型別檢查器處理,類似於使用@dataclasses.dataclass
建立的類。例如,型別檢查器將假定這些類具有接受id
和name
的__init__
方法。被裝飾的類、元類或函式可以接受以下布林引數,型別檢查器將假定它們具有與
@dataclasses.dataclass
裝飾器相同的效果:init
、eq
、order
、unsafe_hash
、frozen
、match_args
、kw_only
和slots
。這些引數的值(True
或False
)必須能夠被靜態評估。dataclass_transform
裝飾器的引數可用於自定義被裝飾類、元類或函式的預設行為- 引數:
eq_default (bool) – 指示如果呼叫者省略
eq
引數,則其值應假定為True
還是False
。預設為True
。order_default (bool) – 指示如果呼叫者省略
order
引數,則其值應假定為True
還是False
。預設為False
。kw_only_default (bool) – 指示如果呼叫者省略
kw_only
引數,則其值應假定為True
還是False
。預設為False
。frozen_default (bool) –
指示如果呼叫者省略
frozen
引數,則其值應假定為True
還是False
。預設為False
。3.12 新版功能.
field_specifiers (tuple[Callable[..., Any], ...]) – 指定支援的類或函式的靜態列表,用於描述欄位,類似於
dataclasses.field()
。預設為()
。**kwargs (Any) – 接受任意其他關鍵字引數,以允許可能的未來擴充套件。
型別檢查器識別字段說明符上的以下可選引數
欄位說明符的識別引數¶ 引數名稱
描述
init
指示欄位是否應包含在合成的
__init__
方法中。如果未指定,init
預設為True
。default
提供欄位的預設值。
default_factory
提供一個執行時回撥,返回欄位的預設值。如果
default
和default_factory
均未指定,則假定該欄位沒有預設值,並且在例項化類時必須提供一個值。factory
欄位說明符上
default_factory
引數的別名。kw_only
指示欄位是否應標記為僅限關鍵字引數。如果為
True
,則該欄位將為僅限關鍵字引數。如果為False
,則它將不是僅限關鍵字引數。如果未指定,則使用用dataclass_transform
裝飾的物件上的kw_only
引數的值,或者如果該引數未指定,則使用dataclass_transform
上的kw_only_default
值。alias
為欄位提供一個替代名稱。此替代名稱用於合成的
__init__
方法。在執行時,此裝飾器將其引數記錄在被裝飾物件的
__dataclass_transform__
屬性中。它沒有其他執行時效果。有關更多詳細資訊,請參閱 PEP 681。
在 3.11 版本中新增。
- @typing.overload¶
用於建立過載函式和方法的裝飾器。
@overload 裝飾器允許描述支援多種不同引數型別組合的函式和方法。一系列 @overload 裝飾的定義之後必須緊跟一個未被 @overload 裝飾的定義(針對同一個函式/方法)。
@overload
裝飾的定義僅用於型別檢查器,因為它們將被非@overload
裝飾的定義覆蓋。同時,非@overload
裝飾的定義將在執行時使用,但應被型別檢查器忽略。在執行時,直接呼叫@overload
裝飾的函式將引發NotImplementedError
。一個過載示例,它提供了比使用 union 或型別變量表達更精確的型別
@overload def process(response: None) -> None: ... @overload def process(response: int) -> tuple[int, str]: ... @overload def process(response: bytes) -> str: ... def process(response): ... # actual implementation goes here
有關更多詳細資訊以及與其他型別語義的比較,請參閱 PEP 484。
版本 3.11 中的變化: 現在可以使用
get_overloads()
在執行時內省過載函式。
- typing.get_overloads(func)¶
返回 func 的
@overload
裝飾定義序列。func 是過載函式實現的函式物件。例如,給定
@overload
文件中的process
定義,get_overloads(process)
將返回三個已定義過載的三個函式物件序列。如果對沒有過載的函式呼叫,get_overloads()
返回一個空序列。get_overloads()
可用於在執行時內省過載函式。在 3.11 版本中新增。
- typing.clear_overloads()¶
清除內部登錄檔中的所有已註冊過載。
這可用於回收登錄檔使用的記憶體。
在 3.11 版本中新增。
- @typing.final¶
指示最終方法和最終類的裝飾器。
使用
@final
裝飾方法向型別檢查器指示該方法不能在子類中被覆蓋。使用@final
裝飾類指示它不能被子類化。例如:
class Base: @final def done(self) -> None: ... class Sub(Base): def done(self) -> None: # Error reported by type checker ... @final class Leaf: ... class Other(Leaf): # Error reported by type checker ...
這些屬性沒有執行時檢查。有關更多詳細資訊,請參閱 PEP 591。
在 3.8 版本加入。
版本 3.11 中的變化: 裝飾器現在將嘗試在被裝飾物件上將
__final__
屬性設定為True
。因此,在執行時可以使用諸如if getattr(obj, "__final__", False)
這樣的檢查來確定物件obj
是否已被標記為 final。如果被裝飾物件不支援設定屬性,則裝飾器將返回未更改的物件,而不引發異常。
- @typing.no_type_check¶
指示註解不是型別提示的裝飾器。
這作為類或函式 裝飾器 起作用。對於類,它遞迴地應用於該類中定義的所有方法和類(但不適用於其超類或子類中定義的方法)。型別檢查器將忽略帶有此裝飾器的函式或類中的所有註解。
@no_type_check
會就地修改被裝飾物件。
- @typing.no_type_check_decorator¶
一個裝飾器,用於賦予另一個裝飾器
no_type_check()
效果。這會將裝飾器封裝在一個東西中,該東西又將裝飾的函式封裝在
no_type_check()
中。自 3.13 版本棄用,將在 3.15 版本中移除: 沒有任何型別檢查器曾新增對
@no_type_check_decorator
的支援。因此,它已被棄用,並將在 Python 3.15 中移除。
- @typing.override¶
指示子類中的方法旨在覆蓋超類中的方法或屬性的裝飾器。
型別檢查器應在用
@override
裝飾的方法實際上沒有覆蓋任何內容時發出錯誤。這有助於防止在更改基類而子類沒有相應更改時可能發生的錯誤。例如:
class Base: def log_status(self) -> None: ... class Sub(Base): @override def log_status(self) -> None: # Okay: overrides Base.log_status ... @override def done(self) -> None: # Error reported by type checker ...
此屬性沒有執行時檢查。
裝飾器將嘗試在被裝飾物件上將
__override__
屬性設定為True
。因此,可以在執行時使用諸如if getattr(obj, "__override__", False)
的檢查來確定物件obj
是否已被標記為覆蓋。如果被裝飾物件不支援設定屬性,裝飾器將返回未更改的物件而不引發異常。有關更多詳細資訊,請參閱 PEP 698。
3.12 新版功能.
- @typing.type_check_only¶
標記類或函式在執行時不可用的裝飾器。
這個裝飾器本身在執行時不可用。它主要用於標記在型別存根檔案中定義的類,如果實現返回私有類的例項
@type_check_only class Response: # private or not available at runtime code: int def get_header(self, name: str) -> str: ... def fetch_response() -> Response: ...
請注意,不建議返回私有類的例項。通常更傾向於將此類類公開。
內省助手¶
- typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)¶
返回包含函式、方法、模組或類物件的型別提示的字典。
這通常與
obj.__annotations__
相同,但此函式對註解字典進行以下更改透過在 globalns、localns 以及(適用時)obj 的 type parameter 名稱空間中評估,處理編碼為字串字面量或
ForwardRef
物件的正向引用。如果未給出 globalns 或 localns,則從 obj 推斷適當的名稱空間字典。None
被替換為types.NoneType
。如果
@no_type_check
已應用於 obj,則返回一個空字典。如果 obj 是類
C
,則該函式返回一個字典,該字典將C
的基類中的註解與C
上直接的註解合併。這是透過遍歷C.__mro__
並迭代組合__annotations__
字典來完成的。在 方法解析順序 中較早出現的類上的註解總是優先於在方法解析順序中較晚出現的類上的註解。該函式遞迴地將所有
Annotated[T, ...]
的出現替換為T
,除非 include_extras 設定為True
(有關更多資訊,請參閱Annotated
)。
另請參閱
annotationlib.get_annotations()
,這是一個更底層的函式,它更直接地返回註解。注意
此函式可能會執行註解中包含的任意程式碼。有關更多資訊,請參閱 內省註解的安全影響。
備註
如果 obj 的註解中的任何前向引用無法解析或不是有效的 Python 程式碼,此函式將引發異常,例如
NameError
。例如,這可能發生在包含前向引用的匯入 類型別名 或在if TYPE_CHECKING
下匯入的名稱。版本 3.11 中的變化: 以前,如果設定了等於
None
的預設值,則會為函式和方法註解新增Optional[t]
。現在,註解原樣返回。
- typing.get_origin(tp)¶
獲取型別的未下標版本:對於
X[Y, Z, ...]
形式的 typing 物件,返回X
。如果
X
是內建類或collections
類的 typing 模組別名,它將被規範化為原始類。如果X
是ParamSpecArgs
或ParamSpecKwargs
的例項,則返回底層ParamSpec
。對於不支援的物件,返回None
。示例:
assert get_origin(str) is None assert get_origin(Dict[str, int]) is dict assert get_origin(Union[int, str]) is Union assert get_origin(Annotated[str, "metadata"]) is Annotated P = ParamSpec('P') assert get_origin(P.args) is P assert get_origin(P.kwargs) is P
在 3.8 版本加入。
- typing.get_args(tp)¶
獲取所有替換已執行的型別引數:對於
X[Y, Z, ...]
形式的 typing 物件,返回(Y, Z, ...)
。如果
X
是包含在另一個泛型型別中的 union 或Literal
,則(Y, Z, ...)
的順序可能與原始引數[Y, Z, ...]
的順序不同,這是由於型別快取。對於不支援的物件,返回()
。示例:
assert get_args(int) == () assert get_args(Dict[int, str]) == (int, str) assert get_args(Union[int, str]) == (int, str)
在 3.8 版本加入。
- typing.get_protocol_members(tp)¶
返回
Protocol
中定義的成員集合。>>> from typing import Protocol, get_protocol_members >>> class P(Protocol): ... def a(self) -> str: ... ... b: int >>> get_protocol_members(P) == frozenset({'a', 'b'}) True
對於不是協議的引數,引發
TypeError
。在 3.13 版本加入。
- typing.is_protocol(tp)¶
判斷一個型別是否為
Protocol
。例如:
class P(Protocol): def a(self) -> str: ... b: int is_protocol(P) # => True is_protocol(int) # => False
在 3.13 版本加入。
- typing.is_typeddict(tp)¶
檢查一個型別是否為
TypedDict
。例如:
class Film(TypedDict): title: str year: int assert is_typeddict(Film) assert not is_typeddict(list | str) # TypedDict is a factory for creating typed dicts, # not a typed dict itself assert not is_typeddict(TypedDict)
在 3.10 版本加入。
- class typing.ForwardRef¶
用於字串前向引用的內部型別表示的類。
例如,
List["SomeClass"]
被隱式轉換為List[ForwardRef("SomeClass")]
。ForwardRef
不應由使用者例項化,但可由內省工具使用。備註
PEP 585 泛型型別(例如
list["SomeClass"]
)不會隱式轉換為list[ForwardRef("SomeClass")]
,因此不會自動解析為list[SomeClass]
。3.7.4 版本新增。
版本 3.14 中的變化: 這現在是
annotationlib.ForwardRef
的別名。此類的幾個未文件行為已更改;例如,在評估ForwardRef
之後,評估值不再快取。
- typing.evaluate_forward_ref(forward_ref, *, owner=None, globals=None, locals=None, type_params=None, format=annotationlib.Format.VALUE)¶
將
annotationlib.ForwardRef
評估為 型別提示。這類似於呼叫
annotationlib.ForwardRef.evaluate()
,但與該方法不同,evaluate_forward_ref()
還會遞迴地評估型別提示中巢狀的前向引用。有關 owner、globals、locals、type_params 和 format 引數的含義,請參閱
annotationlib.ForwardRef.evaluate()
的文件。注意
此函式可能會執行註解中包含的任意程式碼。有關更多資訊,請參閱 內省註解的安全影響。
在 3.14 版本加入。
- typing.NoDefault¶
一個哨兵物件,用於指示型別引數沒有預設值。例如
>>> T = TypeVar("T") >>> T.__default__ is typing.NoDefault True >>> S = TypeVar("S", default=None) >>> S.__default__ is None True
在 3.13 版本加入。
常量¶
- typing.TYPE_CHECKING¶
一個特殊常量,被第三方靜態型別檢查器假定為
True
。它在執行時為False
。一個匯入開銷大,且僅包含用於型別註解的型別的模組,可以安全地匯入在
if TYPE_CHECKING:
塊中。這阻止了該模組在執行時實際匯入;註解不會急切地評估(參見 PEP 649),因此在註解中使用未定義的符號是無害的——只要您以後不檢查它們。您的靜態型別分析工具將在靜態型別分析期間將TYPE_CHECKING
設定為True
,這意味著該模組將被匯入,並且在這樣的分析期間型別將被正確檢查。用法
if TYPE_CHECKING: import expensive_mod def fun(arg: expensive_mod.SomeType) -> None: local_var: expensive_mod.AnotherType = other_fun()
如果您偶爾需要在執行時檢查可能包含未定義符號的型別註解,請使用
annotationlib.get_annotations()
並將format
引數設定為annotationlib.Format.STRING
或annotationlib.Format.FORWARDREF
,以安全地檢索註解而不會引發NameError
。3.5.2 版本新增。
已棄用的別名¶
此模組定義了幾個已棄用的別名,指向預先存在的標準庫類。這些別名最初包含在 typing
模組中,以支援使用 []
對這些泛型類進行引數化。然而,在 Python 3.9 中,當相應的預先存在的類被增強以支援 []
時(參見 PEP 585),這些別名變得多餘。
這些冗餘型別自 Python 3.9 起已棄用。但是,雖然這些別名可能會在某個時候被刪除,但目前沒有計劃刪除它們。因此,直譯器目前不會為這些別名發出棄用警告。
如果在某個時候決定刪除這些已棄用的別名,直譯器將在刪除前至少兩個版本發出棄用警告。這些別名保證在 typing
模組中保留,且不發出棄用警告,直到至少 Python 3.14。
建議型別檢查器在程式目標最小 Python 版本為 3.9 或更高版本時,標記已棄用型別的使用。
內建型別的別名¶
- class typing.Dict(dict, MutableMapping[KT, VT])¶
已棄用的
dict
別名。請注意,為了註解引數,最好使用抽象集合型別(如
Mapping
),而不是使用dict
或typing.Dict
。自 3.9 版本棄用:
builtins.dict
現在支援下標([]
)。請參閱 PEP 585 和 泛型別名型別。
- class typing.List(list, MutableSequence[T])¶
已棄用的
list
別名。請注意,為了註解引數,最好使用抽象集合型別(如
Sequence
或Iterable
),而不是使用list
或typing.List
。自 3.9 版本棄用:
builtins.list
現在支援下標([]
)。請參閱 PEP 585 和 泛型別名型別。
- class typing.Set(set, MutableSet[T])¶
已棄用的
builtins.set
別名。請注意,為了註解引數,最好使用抽象集合型別(如
collections.abc.Set
),而不是使用set
或typing.Set
。自 3.9 版本棄用:
builtins.set
現在支援下標([]
)。請參閱 PEP 585 和 泛型別名型別。
- class typing.FrozenSet(frozenset, AbstractSet[T_co])¶
已棄用的
builtins.frozenset
別名。自 3.9 版本棄用:
builtins.frozenset
現在支援下標([]
)。請參閱 PEP 585 和 泛型別名型別。
collections
中型別的別名¶
- class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])¶
已棄用的
collections.defaultdict
別名。3.5.2 版本新增。
自 3.9 版本棄用:
collections.defaultdict
現在支援下標([]
)。請參閱 PEP 585 和 泛型別名型別。
- class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])¶
已棄用的
collections.OrderedDict
別名。3.7.2 版本新增。
自 3.9 版本棄用:
collections.OrderedDict
現在支援下標([]
)。請參閱 PEP 585 和 泛型別名型別。
- class typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT])¶
已棄用的
collections.ChainMap
別名。3.6.1 版本新增。
自 3.9 版本棄用:
collections.ChainMap
現在支援下標([]
)。請參閱 PEP 585 和 泛型別名型別。
- class typing.Counter(collections.Counter, Dict[T, int])¶
已棄用的
collections.Counter
別名。3.6.1 版本新增。
自 3.9 版本棄用:
collections.Counter
現在支援下標([]
)。請參閱 PEP 585 和 泛型別名型別。
- class typing.Deque(deque, MutableSequence[T])¶
已棄用的
collections.deque
別名。3.6.1 版本新增。
自 3.9 版本棄用:
collections.deque
現在支援下標([]
)。請參閱 PEP 585 和 泛型別名型別。
其他具體型別的別名¶
- class typing.Pattern¶
- class typing.Match¶
已棄用的別名,對應於
re.compile()
和re.match()
的返回型別。這些型別(和相應的函式)是泛型於
AnyStr
的。Pattern
可以特化為Pattern[str]
或Pattern[bytes]
;Match
可以特化為Match[str]
或Match[bytes]
。
- class typing.Text¶
str
的棄用別名。提供
Text
是為了給 Python 2 程式碼提供一個向前相容的路徑:在 Python 2 中,Text
是unicode
的別名。使用
Text
來表示一個值必須包含一個與 Python 2 和 Python 3 都相容的 unicode 字串。def add_unicode_checkmark(text: Text) -> Text: return text + u' \u2713'
3.5.2 版本新增。
自 3.11 版本棄用: Python 2 已不再受支援,並且大多數型別檢查器也不再支援對 Python 2 程式碼進行型別檢查。目前沒有計劃移除此別名,但鼓勵使用者使用
str
而不是Text
。
collections.abc
中的容器抽象基類的別名¶
- class typing.AbstractSet(Collection[T_co])¶
collections.abc.Set
的棄用別名。自 3.9 版本棄用:
collections.abc.Set
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.ByteString(Sequence[int])¶
collections.abc.ByteString
的棄用別名。在執行時,使用
isinstance(obj, collections.abc.Buffer)
來測試obj
是否實現了緩衝區協議。在型別註解中,可以使用Buffer
或顯式指定程式碼支援的型別的聯合(例如,bytes | bytearray | memoryview
)。ByteString
最初旨在成為一個抽象類,它將作為bytes
和bytearray
的超型別。然而,由於這個 ABC 從未有任何方法,因此知道一個物件是ByteString
的例項實際上並未提供任何有用的資訊。其他常見的緩衝區型別,如memoryview
,也從未被視為ByteString
的子型別(無論是執行時還是靜態型別檢查器)。更多詳情請參見 PEP 688。
自 3.9 版本棄用,將於 3.17 版本移除。
- class typing.Collection(Sized, Iterable[T_co], Container[T_co])¶
collections.abc.Collection
的棄用別名。在 3.6 版本加入。
自 3.9 版本棄用:
collections.abc.Collection
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.Container(Generic[T_co])¶
collections.abc.Container
的棄用別名。自 3.9 版本棄用:
collections.abc.Container
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.ItemsView(MappingView, AbstractSet[tuple[KT_co, VT_co]])¶
collections.abc.ItemsView
的棄用別名。自 3.9 版本棄用:
collections.abc.ItemsView
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.KeysView(MappingView, AbstractSet[KT_co])¶
collections.abc.KeysView
的棄用別名。自 3.9 版本棄用:
collections.abc.KeysView
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.Mapping(Collection[KT], Generic[KT, VT_co])¶
collections.abc.Mapping
的棄用別名。自 3.9 版本棄用:
collections.abc.Mapping
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.MappingView(Sized)¶
collections.abc.MappingView
的棄用別名。自 3.9 版本棄用:
collections.abc.MappingView
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.MutableMapping(Mapping[KT, VT])¶
collections.abc.MutableMapping
的棄用別名。自 3.9 版本棄用:
collections.abc.MutableMapping
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.MutableSequence(Sequence[T])¶
collections.abc.MutableSequence
的棄用別名。自 3.9 版本棄用:
collections.abc.MutableSequence
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.MutableSet(AbstractSet[T])¶
collections.abc.MutableSet
的棄用別名。自 3.9 版本棄用:
collections.abc.MutableSet
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.Sequence(Reversible[T_co], Collection[T_co])¶
collections.abc.Sequence
的棄用別名。自 3.9 版本棄用:
collections.abc.Sequence
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.ValuesView(MappingView, Collection[_VT_co])¶
collections.abc.ValuesView
的棄用別名。自 3.9 版本棄用:
collections.abc.ValuesView
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
collections.abc
中的非同步抽象基類的別名¶
- class typing.Coroutine(Awaitable[ReturnType], Generic[YieldType, SendType, ReturnType])¶
collections.abc.Coroutine
的棄用別名。有關在型別註解中使用
collections.abc.Coroutine
和typing.Coroutine
的詳細資訊,請參見 註解生成器和協程。3.5.3 版本新增。
自 3.9 版本棄用:
collections.abc.Coroutine
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.AsyncGenerator(AsyncIterator[YieldType], Generic[YieldType, SendType])¶
collections.abc.AsyncGenerator
的棄用別名。有關在型別註解中使用
collections.abc.AsyncGenerator
和typing.AsyncGenerator
的詳細資訊,請參見 註解生成器和協程。3.6.1 版本新增。
自 3.9 版本棄用:
collections.abc.AsyncGenerator
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。3.13 版本中的變化:
SendType
引數現在有預設值。
- class typing.AsyncIterable(Generic[T_co])¶
collections.abc.AsyncIterable
的棄用別名。3.5.2 版本新增。
自 3.9 版本棄用:
collections.abc.AsyncIterable
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.AsyncIterator(AsyncIterable[T_co])¶
collections.abc.AsyncIterator
的棄用別名。3.5.2 版本新增。
自 3.9 版本棄用:
collections.abc.AsyncIterator
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.Awaitable(Generic[T_co])¶
collections.abc.Awaitable
的棄用別名。3.5.2 版本新增。
自 3.9 版本棄用:
collections.abc.Awaitable
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
collections.abc
中其他抽象基類的別名¶
- class typing.Iterable(Generic[T_co])¶
collections.abc.Iterable
的棄用別名。自 3.9 版本棄用:
collections.abc.Iterable
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.Iterator(Iterable[T_co])¶
collections.abc.Iterator
的棄用別名。自 3.9 版本棄用:
collections.abc.Iterator
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- typing.Callable¶
collections.abc.Callable
的棄用別名。有關如何在型別註解中使用
collections.abc.Callable
和typing.Callable
的詳細資訊,請參見 註解可呼叫物件。自 3.9 版本棄用:
collections.abc.Callable
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。3.10 版本中的變化:
Callable
現在支援ParamSpec
和Concatenate
。更多詳情請參見 PEP 612。
- class typing.Generator(Iterator[YieldType], Generic[YieldType, SendType, ReturnType])¶
collections.abc.Generator
的棄用別名。有關在型別註解中使用
collections.abc.Generator
和typing.Generator
的詳細資訊,請參見 註解生成器和協程。自 3.9 版本棄用:
collections.abc.Generator
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。3.13 版本中的變化: 添加了傳送和返回型別的預設值。
- class typing.Hashable¶
collections.abc.Hashable
的棄用別名。自 3.12 版本棄用: 請直接使用
collections.abc.Hashable
。
- class typing.Reversible(Iterable[T_co])¶
collections.abc.Reversible
的棄用別名。自 3.9 版本棄用:
collections.abc.Reversible
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。
- class typing.Sized¶
collections.abc.Sized
的棄用別名。自 3.12 版本棄用: 請直接使用
collections.abc.Sized
。
contextlib
抽象基類的別名¶
- class typing.ContextManager(Generic[T_co, ExitT_co])¶
contextlib.AbstractContextManager
的棄用別名。第一個型別引數
T_co
代表由__enter__()
方法返回的型別。可選的第二個型別引數ExitT_co
(預設為bool | None
)代表由__exit__()
方法返回的型別。在 3.5.4 版本中新增。
自 3.9 版本棄用:
contextlib.AbstractContextManager
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。3.13 版本中的變化: 添加了可選的第二個型別引數
ExitT_co
。
- class typing.AsyncContextManager(Generic[T_co, AExitT_co])¶
contextlib.AbstractAsyncContextManager
的棄用別名。第一個型別引數
T_co
代表由__aenter__()
方法返回的型別。可選的第二個型別引數AExitT_co
(預設為bool | None
)代表由__aexit__()
方法返回的型別。在 3.6.2 版本中新增。
自 3.9 版本棄用:
contextlib.AbstractAsyncContextManager
現在支援下標 ([]
)。參見 PEP 585 和 泛型別名型別。3.13 版本中的變化: 添加了可選的第二個型別引數
AExitT_co
。
主要功能棄用時間表¶
typing
中的某些功能已棄用,並可能在未來版本的 Python 中移除。下表總結了主要的棄用功能,以方便查閱。此表可能會有變動,並非所有棄用功能都已列出。
功能 |
棄用版本 |
預計移除版本 |
PEP/問題 |
---|---|---|---|
|
3.9 |
未定(詳見 棄用別名) |
|
3.9 |
3.17 |
||
3.11 |
未定 |
||
3.12 |
未定 |
||
3.12 |
未定 |
||
3.13 |
3.15 |
||
3.13 |
3.18 |