typing
— 型別提示支援¶
3.5 版本中新增。
原始碼: Lib/typing.py
註解
Python 執行時不強制執行函式和變數型別註解。它們可以被第三方工具使用,例如型別檢查器、IDE、程式碼檢查器等。
此模組為型別提示提供執行時支援。
考慮下面的函式
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 型別系統透過 PEP 進行標準化,因此此參考應廣泛適用於大多數 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)
在執行時始終為 true。
建立 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]]
也可以使用顯式繼承自 Generic
的方式建立基於 ParamSpec
的泛型類。在這種情況下,不使用 **
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__
,因為它們主要用於靜態型別檢查。
使用者定義的泛型類可以將 ABC 作為基類,而不會發生元類衝突。不支援泛型元類。引數化泛型的結果被快取,並且 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")
標稱子型別 vs 結構子型別¶
最初,PEP 484 將 Python 靜態型別系統定義為使用標稱子型別。這意味著,當且僅當 A
是 B
的子類時,才允許使用類 A
代替預期使用類 B
的情況。
此要求之前也適用於抽象基類,例如 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
語句。
特殊形式¶
這些可以用作註解中的型別。它們都支援使用 []
進行下標訪問,但每個都有獨特的語法。
- typing.Union¶
聯合型別;
Union[X, Y]
等價於X | Y
,表示 X 或 Y。要定義聯合型別,請使用例如
Union[int, str]
或簡寫形式int | str
。推薦使用簡寫形式。詳情引數必須是型別,且必須至少有一個。
聯合型別的聯合將被展平,例如:
Union[Union[int, str], 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
編寫聯合型別。請參閱 聯合型別表示式。
- 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 版本中更改: 現在可以使用
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。在 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
。因此,Annotated
對於希望在 Python 的靜態型別系統之外使用註解的程式碼很有用。使用
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 Annotated[int, ValueRange(3, 10), ctype("char")]
由使用註解的工具決定是否允許客戶端向一個註解新增多個元資料元素以及如何合併這些註解。
Annotated
必須至少使用兩個引數進行下標化(Annotated[int]
無效)元資料元素的順序會被保留,並且對相等性檢查很重要
assert Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[ int, ctype("char"), ValueRange(3, 10) ]
巢狀的
Annotated
型別會被展平。元資料元素的順序從最內層的註解開始assert Annotated[Annotated[int, ValueRange(3, 10)], 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] # NOT valid
這相當於
Annotated[T1, T2, T3, ..., Ann1]
其中
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'>}
在執行時,可以透過
__metadata__
屬性檢索與Annotated
型別關聯的元資料>>> 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 - 靈活的函式和變數註解
將
Annotated
引入標準庫的 PEP。
在 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__¶
型別變數的上界(如果有)。
- __constraints__¶
一個元組,包含型別變數的約束(如果有)。
- __default__¶
型別變數的預設值,如果沒有預設值,則為
typing.NoDefault
。在 3.13 版本中新增。
- 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 版本中新增。
- 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 版本中新增。
- 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__ ()
其他特殊指令¶
這些函式和類不應直接用作註解。它們的預期目的是作為建立和宣告型別的構建塊。
- 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()
(稍後描述)修飾的協議類充當簡單的執行時協議,僅檢查給定屬性的存在,而忽略其型別簽名。協議類可以是泛型的,例如
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()
一起使用。當應用於非協議類時,這將引發TypeError
異常。這允許簡單的結構檢查,非常類似於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)
註解
runtime_checkable()
將僅檢查所需方法或屬性的存在,而不檢查其型別簽名或型別。例如,ssl.SSLObject
是一個類,因此它通過了針對 Callable 的issubclass()
檢查。但是,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 # OK, functional syntax Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
預設情況下,所有鍵都必須存在於
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
是預設值,並使類主體中定義的所有項都是必需的。可以使用
Required
將total=False
TypedDict
的單個鍵標記為必需的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]
可以透過 annotations dicts(有關注釋最佳實踐的更多資訊,請參見 註釋最佳實踐)、
__total__
、__required_keys__
和__optional_keys__
來內省TypedDict
。- __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。例如,將__total__
設定為True
的TypedDict
可能具有用NotRequired
標記的鍵,或者它可能繼承自total=False
的另一個TypedDict
。因此,通常最好使用__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
中宣告必需鍵和非必需鍵。這透過宣告一個帶有total
引數的一個值的TypedDict
,然後在另一個帶有total
的不同值的TypedDict
中繼承它來完成。>>> 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
的更多示例和詳細規則,請參閱 PEP 589。在 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")
)已被棄用。將None
傳遞給 'fields' 引數(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__
,其返回型別是協變的。
用於處理 IO 的 ABC¶
函式和裝飾器¶
- 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)
在此,型別註解允許型別檢查器推斷出最後一種情況永遠不會執行,因為
arg
要麼是int
,要麼是str
,並且這兩種情況都已被前面的情況覆蓋。如果型別檢查器發現對
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
行為的裝飾器。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
型別檢查器將以類似於使用
@dataclasses.dataclass
建立的類的方式處理上面定義的CustomerModel
類。 例如,型別檢查器將假定這些類具有接受id
和name
的__init__
方法。被裝飾的類、元類或函式可能接受以下 bool 引數,型別檢查器會假定這些引數具有與它們在
@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
值。別名
為該欄位提供一個替代名稱。此替代名稱用於合成的
__init__
方法中。在執行時,此裝飾器將其引數記錄在被修飾物件的
__dataclass_transform__
屬性中。它沒有其他執行時效果。有關更多詳細資訊,請參閱 PEP 681。
在 3.11 版本中新增。
- @typing.overload¶
用於建立過載函式和方法的裝飾器。
@overload
裝飾器允許描述支援多種不同引數型別組合的函式和方法。一系列@overload
修飾的定義後面必須跟一個且只有一個非@overload
修飾的定義(對於同一函式/方法)。@overload
修飾的定義僅供型別檢查器使用,因為它們將被非@overload
修飾的定義覆蓋。與此同時,非@overload
修飾的定義將在執行時使用,但應被型別檢查器忽略。在執行時,直接呼叫@overload
修飾的函式將引發NotImplementedError
。一個過載示例,它提供比使用聯合或型別變數可以表達的更精確的型別
@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
是否被標記為最終的。如果修飾的物件不支援設定屬性,則該裝飾器將返回未更改的物件,而不會引發異常。
- @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__
相同,但此函式對註解字典進行了以下更改編碼為字串字面量或
ForwardRef
物件的前向引用透過在 globalns、localns 和(如果適用)obj 的型別引數名稱空間中計算它們來處理。如果未給出 globalns 或 localns,則從 obj 推斷出適當的名稱空間字典。None
將被替換為types.NoneType
。如果
@no_type_check
已應用於 obj,則返回一個空字典。如果 obj 是一個類
C
,該函式返回一個字典,該字典合併了來自C
的基類的註解以及直接在C
上的註解。這是透過遍歷C.__mro__
並迭代地組合__annotations__
字典來完成的。在 方法解析順序 中較早出現的類上的註解始終優先於方法解析順序中較晚出現的類上的註解。除非將 include_extras 設定為
True
(有關更多資訊,請參見Annotated
),否則該函式會遞迴地將所有出現的Annotated[T, ...]
替換為T
。
另請參見
inspect.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
是一個聯合型別或包含在另一個泛型型別中的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
對於不是 Protocol 的引數,引發
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 版本中新增。
- 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: import expensive_mod def fun(arg: 'expensive_mod.SomeType') -> None: local_var: expensive_mod.AnotherType = other_fun()
第一個型別註解必須用引號括起來,使其成為“前向引用”,以隱藏直譯器執行時的
expensive_mod
引用。不會評估區域性變數的型別註解,因此第二個註解不需要用引號括起來。註解
如果使用
from __future__ import annotations
,則不會在函式定義時評估註解。相反,它們作為字串儲存在__annotations__
中。這使得無需在註解周圍使用引號(請參閱 PEP 563)。在 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
中容器 ABC 的別名¶
- class typing.AbstractSet(Collection[T_co])¶
已棄用的
collections.abc.Set
別名。3.9 版本起已棄用:
collections.abc.Set
現在支援下標([]
)。請參閱 PEP 585 和 泛型別名型別。
- class typing.ByteString(Sequence[int])¶
此型別表示位元組序列的型別
bytes
、bytearray
和memoryview
。3.9 版本起已棄用,將在 3.14 版本中移除: 首選
collections.abc.Buffer
,或像bytes | bytearray | memoryview
這樣的聯合型別。
- 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
中非同步 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
中其他 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
中的 ABC 的別名¶
- 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/issue |
---|---|---|---|
|
3.9 |
未定(更多資訊請參閱 已棄用的別名) |
|
3.9 |
3.14 |
||
3.11 |
未定 |
||
3.12 |
未定 |
||
3.12 |
未定 |
||
3.13 |
3.15 |
||
3.13 |
3.18 |