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