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 提示所示。

雖然型別提示可以是像 floatstr 這樣的簡單類,但它們也可以更復雜。typing 模組提供了更高階的型別提示詞彙。

typing 模組經常會新增新功能。typing_extensions 包為舊版本的 Python 提供了這些新功能的向後移植。

參見

“型別提示備忘單”

型別提示的快速概述(託管在 mypy 文件中)

mypy 文件的“型別系統參考”部分

Python 型別系統透過 PEP 進行標準化,因此此參考應廣泛適用於大多數 Python 型別檢查器。(某些部分可能仍然特定於 mypy。)

“Python 的靜態型別”

由社群編寫的與型別檢查器無關的文件,詳細介紹了型別系統功能、有用的型別相關工具和型別最佳實踐。

Python 型別系統的規範

Python 型別系統的規範、最新規範可以在“Python 型別系統規範”中找到。

類型別名

類型別名使用 type 語句定義,該語句建立 TypeAliasType 的例項。在此示例中,靜態型別檢查器會將 Vectorlist[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

訂閱語法必須始終與恰好兩個值一起使用:引數列表和返回型別。引數列表必須是型別列表、ParamSpecConcatenate 或省略號。返回型別必須是單個型別。

如果將字面省略號 ... 作為引數列表給出,則表示接受任何任意引數列表的可呼叫物件。

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 現在支援 ParamSpecConcatenate。有關更多詳細資訊,請參閱 PEP 612

參見

ParamSpecConcatenate 的文件提供了在 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

type[Any] 等效於 type,它是 Python 的元類層次結構的根。

註釋生成器和協程

可以使用泛型型別 Generator[YieldType, SendType, ReturnType] 來註釋生成器。例如

def echo_round() -> Generator[int, float, str]:
    sent = yield 0
    while sent >= 0:
        sent = yield round(sent)
    return 'Done'

請注意,與標準庫中的許多其他泛型類不同,GeneratorSendType 的行為是逆變的,而不是協變或不變的。

SendTypeReturnType 引數預設為 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]):
    ...

TypeVarParamSpec 之間的另一個區別是,對於只有一個引數規範變數的泛型,出於美觀的原因,將接受 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__,因為它們主要用於靜態型別檢查。

在 3.10 版本中更改: Generic 現在可以透過引數表示式進行引數化。有關詳細資訊,請參閱 ParamSpecPEP 612

使用者定義的泛型類可以將 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")

使用 object 來表示一個值可以是以型別安全的方式進行的任何型別。使用 Any 來表示一個值是動態型別的。

標稱子型別 vs 結構子型別

最初,PEP 484 將 Python 靜態型別系統定義為使用標稱子型別。這意味著,當且僅當 AB 的子類時,才允許使用類 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 視為 SizedIterable[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.Any

指示無約束型別的特殊型別。

  • 每個型別都與 Any 相容。

  • Any 與每個型別相容。

在 3.11 版本中更改: Any 現在可以用作基類。這對於避免在任何地方都可以進行鴨子型別或高度動態的類出現型別檢查器錯誤非常有用。

typing.AnyStr

一個 約束型別變數

定義

AnyStr = TypeVar('AnyStr', str, bytes)

AnyStr 用於可能接受 strbytes 引數,但不允許兩者混合的函式。

例如

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

請注意,儘管名稱如此,AnyStrAny 型別沒有任何關係,也不意味著“任何字串”。 特別是,AnyStrstr | 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!"

自 3.13 版本起已棄用,將在 3.18 版本中刪除: 棄用,轉而使用新的 型別引數語法。使用 class A[T: (str, bytes)]: ... 而不是匯入 AnyStr。有關更多詳細資訊,請參閱 PEP 695

在 Python 3.16 中,AnyStr 將從 typing.__all__ 中刪除,並且在從 typing 訪問或匯入時,將在執行時發出棄用警告。AnyStr 將在 Python 3.18 中從 typing 中刪除。

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

NeverNoReturn 表示 底部型別,即沒有成員的型別。

它們可用於指示函式永遠不會返回,例如 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)

NeverNoReturn 在型別系統中具有相同的含義,並且靜態型別檢查器對兩者都同等對待。

在 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 的例項,並且原生支援前向引用。請注意,雖然 TypeAliasTypeAliasType 的目的相似且名稱相近,但它們是不同的,後者不是前者的型別。目前沒有計劃移除 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 可以與 CallableParamSpec 一起使用,以註解一個高階可呼叫物件,該物件新增、刪除或轉換另一個可呼叫物件的引數。用法形式為 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 版本中新增。

在 3.9.1 版本中更改: Literal 現在會刪除重複的引數。Literal 物件的相等性比較不再依賴於順序。Literal 物件在相等性比較期間,如果其引數之一不是 可雜湊的,則會引發 TypeError 異常。

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 版本中新增。

在 3.13 版本中更改: ClassVar 現在可以巢狀在 Final 中,反之亦然。

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 版本中新增。

在 3.13 版本中更改: Final 現在可以巢狀在 ClassVar 中,反之亦然。

typing.Required

用於將 TypedDict 鍵標記為必需的特殊型別構造。

這主要對 total=False 的 TypedDicts 有用。更多詳細資訊,請參閱 TypedDictPEP 655

在 3.11 版本中新增。

typing.NotRequired

特殊的型別構造,用於將 TypedDict 的鍵標記為可能缺失。

更多詳細資訊,請參閱 TypedDictPEP 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

此屬性沒有執行時檢查。

更多詳細資訊,請參閱 TypedDictPEP 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] 告訴靜態型別檢查器,對於給定的函式

  1. 返回值是一個布林值。

  2. 如果返回值是 True,則其引數的型別是引數的原始型別和 NarrowedType 的交集。

  3. 如果返回值是 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 中的型別對映到第二個引數的型別(在 clsself 之後)。

簡而言之,形式為 def foo(arg: TypeA) -> TypeIs[TypeB]: ... 的函式,意味著如果 foo(arg) 返回 True,則 argTypeB 的例項;如果返回 False,則不是 TypeB 的例項。

TypeIs 也適用於型別變數。更多資訊,請參閱 PEP 742 (使用 TypeIs 縮小型別)。

在 3.13 版本中新增。

typing.TypeGuard

用於標記使用者定義的型別謂詞函式的特殊型別構造。

型別謂詞函式是使用者定義的函式,用於返回其引數是否為特定型別的例項。TypeGuard 的工作方式類似於 TypeIs,但對型別檢查行為有細微的不同影響(見下文)。

使用 -> TypeGuard 告訴靜態型別檢查器,對於給定的函式

  1. 返回值是一個布林值。

  2. 如果返回值是 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!")

TypeIsTypeGuard 在以下方面有所不同

  • 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.TypeVarTuplebuiltins.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=Truecontravariant=True 將手動建立的型別變數顯式標記為協變或逆變。預設情況下,手動建立的型別變數是不變的。有關更多詳細資訊,請參閱 PEP 484PEP 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__

型別變數的上界(如果有)。

3.12 版本更改: 對於透過型別引數語法建立的型別變數,其邊界僅在訪問屬性時才進行計算,而不是在建立型別變數時計算(參見延遲計算)。

__constraints__

一個元組,包含型別變數的約束(如果有)。

3.12 版本更改: 對於透過型別引數語法建立的型別變數,其約束僅在訪問屬性時才進行計算,而不是在建立型別變數時計算(參見延遲計算)。

__default__

型別變數的預設值,如果沒有預設值,則為typing.NoDefault

在 3.13 版本中新增。

has_default()

返回型別變數是否具有預設值。這等效於檢查__default__是否不是typing.NoDefault單例,但它不會強制計算延遲計算的預設值。

在 3.13 版本中新增。

3.12 版本更改: 現在可以使用PEP 695引入的型別引數語法來宣告型別變數。添加了 infer_variance 引數。

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.12 版本更改: 現在可以使用PEP 695引入的型別引數語法來宣告型別變數元組。

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。但是,這會導致兩個問題:

  1. 型別檢查器無法型別檢查 inner 函式,因為 *args**kwargs 必須被型別化為 Any

  2. 在返回 inner 函式時,可能需要在 add_logging 裝飾器的正文中呼叫 cast(),否則必須告知靜態型別檢查器忽略 return inner

args
kwargs

由於 ParamSpec 同時捕獲位置引數和關鍵字引數,P.argsP.kwargs 可以用來將 ParamSpec 分解為其組成部分。P.args 表示給定呼叫中的位置引數元組,並且應該僅用於註解 *argsP.kwargs 表示給定呼叫中關鍵字引數到其值的對映,並且應該僅用於註解 **kwargs。這兩個屬性都要求被註解的引數在作用域內。在執行時,P.argsP.kwargs 分別是 ParamSpecArgsParamSpecKwargs 的例項。

__name__

引數規範的名稱。

__default__

引數規範的預設值,或者如果沒有預設值,則為 typing.NoDefault

在 3.13 版本中新增。

has_default()

返回引數規範是否具有預設值。這等效於檢查 __default__ 是否不是 typing.NoDefault 單例,只是它不會強制評估 延遲評估 的預設值。

在 3.13 版本中新增。

使用 covariant=Truecontravariant=True 建立的引數規範變數可用於宣告協變或逆變泛型型別。bound 引數也被接受,類似於 TypeVar。但是,這些關鍵字的實際語義尚未確定。

在 3.10 版本中新增。

在 3.12 版本中更改: 現在可以使用 PEP 695 引入的 型別引數 語法來宣告引數規範。

3.13 版本更改: 添加了對預設值的支援。

註解

只有在全域性作用域中定義的引數規範變數才能被 pickle 序列化。

參見

typing.ParamSpecArgs
typing.ParamSpecKwargs

ParamSpec 的引數和關鍵字引數屬性。 ParamSpecP.args 屬性是 ParamSpecArgs 的例項,P.kwargsParamSpecKwargs 的例項。它們旨在用於執行時自省,對靜態型別檢查器沒有特殊含義。

在這些物件中的任何一個上呼叫 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

其他特殊指令

這些函式和類不應直接用作註解。它們的預期目的是作為建立和宣告型別的構建塊。

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’ 引數傳遞 NoneNT = NamedTuple("NT", None))也被棄用。這兩個用法將在 Python 3.15 中被禁止。要建立具有 0 個欄位的 NamedTuple 類,請使用 class NT(NamedTuple): passNT = 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 是一個類,因此它通過了針對 Callableissubclass() 檢查。但是,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 可以省略任何鍵。型別檢查器僅應支援字面量 FalseTrue 作為 total 引數的值。True 是預設值,並使類主體中定義的所有項都是必需的。

可以使用 Requiredtotal=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 有三個項:xyz。它等效於此定義

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__ 設定為 TrueTypedDict 可能具有用 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 的支援反映在以下屬性中

__readonly_keys__

一個 frozenset,包含所有隻讀鍵的名稱。如果鍵帶有 ReadOnly 限定符,則它們是隻讀的。

在 3.13 版本中新增。

__mutable_keys__

一個 frozenset,包含所有可變鍵的名稱。如果鍵沒有 ReadOnly 限定符,則它們是可變的。

在 3.13 版本中新增。

有關使用 TypedDict 的更多示例和詳細規則,請參閱 PEP 589

在 3.8 版本中新增。

3.11 版本更改: 添加了將單個鍵標記為 RequiredNotRequired 的支援。請參閱 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): passTD = 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

class typing.IO
class typing.TextIO
class typing.BinaryIO

泛型型別 IO[AnyStr] 及其子類 TextIO(IO[str])BinaryIO(IO[bytes]) 表示 I/O 流的型別,例如 open() 返回的型別。

函式和裝飾器

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 類。 例如,型別檢查器將假定這些類具有接受 idname__init__ 方法。

被裝飾的類、元類或函式可能接受以下 bool 引數,型別檢查器會假定這些引數具有與它們在 @dataclasses.dataclass 裝飾器上相同的作用: initeqorderunsafe_hashfrozenmatch_argskw_onlyslots。 這些引數的值(TrueFalse)必須可以靜態求值。

dataclass_transform 裝飾器的引數可用於自定義被裝飾的類、元類或函式的預設行為。

引數:
  • eq_default (bool) – 指示如果呼叫者省略了 eq 引數,是否假定該引數為 TrueFalse。 預設為 True

  • order_default (bool) – 指示如果呼叫者省略了 order 引數,是否假定該引數為 TrueFalse。 預設為 False

  • kw_only_default (bool) – 指示如果呼叫者省略了 kw_only 引數,是否假定該引數為 TrueFalse。 預設為 False

  • frozen_default (bool) –

    指示如果呼叫者省略了 frozen 引數,是否假定該引數為 TrueFalse。 預設為 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 物件的前向引用透過在 globalnslocalns 和(如果適用)obj型別引數名稱空間中計算它們來處理。如果未給出 globalnslocalns,則從 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.9 版本中更改: 添加了 include_extras 引數,作為 PEP 593 的一部分。有關更多資訊,請參見有關 Annotated 的文件。

在 3.11 版本中更改: 以前,如果設定了等於 None 的預設值,則為函式和方法註解新增 Optional[t]。現在,註解將按原樣返回。

typing.get_origin(tp)

獲取型別的未訂閱版本:對於 X[Y, Z, ...] 形式的 typing 物件,返回 X

如果 X 是內建類或 collections 類的 typing 模組別名,則它將被標準化為原始類。如果 XParamSpecArgsParamSpecKwargs 的例項,則返回底層的 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),而不是使用 dicttyping.Dict

在 3.9 版本中已棄用: builtins.dict 現在支援下標 ([])。請參閱 PEP 585泛型別名型別

class typing.List(list, MutableSequence[T])

已棄用的 list 的別名。

請注意,為了註釋引數,最好使用抽象集合型別,例如 SequenceIterable,而不是使用 listtyping.List

3.9 版本起已棄用: builtins.list 現在支援下標 ( [] )。請參閱 PEP 585通用別名型別

class typing.Set(set, MutableSet[T])

已棄用的 builtins.set 的別名。

請注意,為了註釋引數,最好使用抽象集合型別,例如 collections.abc.Set,而不是使用 settyping.Set

3.9 版本起已棄用: builtins.set 現在支援下標 ( [] )。請參閱 PEP 585通用別名型別

class typing.FrozenSet(frozenset, AbstractSet[T_co])

已棄用的 builtins.frozenset 的別名。

3.9 版本起已棄用: builtins.frozenset 現在支援下標 ( [] )。請參閱 PEP 585通用別名型別

typing.Tuple

已棄用的 tuple 的別名。

tupleTuple 在型別系統中是特殊情況;有關更多詳細資訊,請參閱 註釋元組

3.9 版本起已棄用: builtins.tuple 現在支援下標 ( [] )。請參閱 PEP 585通用別名型別

class typing.Type(Generic[CT_co])

已棄用的 type 的別名。

有關在型別註釋中使用 typetyping.Type 的詳細資訊,請參閱 類物件的型別

在 3.5.2 版本中新增。

3.9 版本起已棄用: builtins.type 現在支援下標 ( [] )。請參閱 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]

3.9 版本起已棄用: re 中的類 PatternMatch 現在支援 []。請參閱 PEP 585泛型別名型別

class typing.Text

已棄用的 str 別名。

提供 Text 是為了為 Python 2 程式碼提供向前相容的路徑:在 Python 2 中,Textunicode 的別名。

使用 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])

此型別表示位元組序列的型別 bytesbytearraymemoryview

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.Coroutinetyping.Coroutine 的詳細資訊,請參閱 註解生成器和協程

在 3.5.3 版本中新增。

3.9 版本起已棄用: collections.abc.Coroutine 現在支援下標操作 ( [] )。參見 PEP 585泛型別名型別

class typing.AsyncGenerator(AsyncIterator[YieldType], Generic[YieldType, SendType])

已棄用的別名,指向 collections.abc.AsyncGenerator

有關在型別註解中使用 collections.abc.AsyncGeneratortyping.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.Callabletyping.Callable 的詳細資訊,請參閱 註解可呼叫物件

自 3.9 版本起已棄用: collections.abc.Callable 現在支援下標操作 ([])。請參閱 PEP 585泛型別名型別

在 3.10 版本中變更: Callable 現在支援 ParamSpecConcatenate。 請參閱 PEP 612 瞭解更多詳情。

class typing.Generator(Iterator[YieldType], Generic[YieldType, SendType, ReturnType])

已棄用的 collections.abc.Generator 別名。

有關在型別註解中使用 collections.abc.Generatortyping.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

typing 版本的標準集合

3.9

未定(更多資訊請參閱 已棄用的別名

PEP 585

typing.ByteString

3.9

3.14

gh-91896

typing.Text

3.11

未定

gh-92332

typing.Hashabletyping.Sized

3.12

未定

gh-94309

typing.TypeAlias

3.12

未定

PEP 695

@typing.no_type_check_decorator

3.13

3.15

gh-106309

typing.AnyStr

3.13

3.18

gh-105578