构造泛型类型与类型别名

下列类不应被直接用作标注。 它们的设计目标是作为创建泛型类型和类型别名的构件。

这些对象可通过特殊语法 (类型形参列表type 语句) 来创建。 为了与 Python 3.11 及更早版本的兼容性,它们也可不用专门的语法来创建,如下文所述。

  • class typing.Generic
  • 用于泛型类型的抽象基类。

泛型类型通常是通过在类名后添加一个类型形参列表来声明的:

  1. class Mapping[KT, VT]:
  2. def __getitem__(self, key: KT) -> VT:
  3. ...
  4. # 其他

这样的类将隐式地继承自 Generic。 对于该语法的运行语义的讨论参见 语言参考

该类的用法如下:

  1. def lookup_name[X, Y](mapping: Mapping[X, Y], key: X, default: Y) -> Y:
  2. try:
  3. return mapping[key]
  4. except KeyError:
  5. return default

此处函数名之后的圆括号是表示 泛型函数

为了保持向下兼容性,泛型类也可通过显式地继承自 Generic 来声明。 在此情况下,类型形参必须单独声明:

  1. KT = TypeVar('KT')
  2. VT = TypeVar('VT')
  3.  
  4. class Mapping(Generic[KT, VT]):
  5. def __getitem__(self, key: KT) -> VT:
  6. ...
  7. # 其他
  • class typing.TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault)
  • 类型变量。

构造类型变量的推荐方式是使用针对 泛型函数, 泛型类泛型类型别名 的专门语法:

  1. class Sequence[T]: # T 是一个 TypeVar
  2. ...

此语法也可被用于创建绑定和约束类型变量:

  1. class StrSequence[S: str]: # S 是具有 `str` 上方绑定的 TypeVar;
  2. ... # 我们可以说 S 是 "被 `str` 绑定"
  3.  
  4.  
  5. class StrOrBytesSequence[A: (str, bytes)]: # A 是约束为 str 或 bytes 的 TypeVar
  6. ...

不过,如有需要,也可通过手动方式来构造可重用的类型变量,就像这样:

  1. T = TypeVar('T') # 可以是任意类型
  2. S = TypeVar('S', bound=str) # 可以是任意 str 的子类型
  3. A = TypeVar('A', str, bytes) # 必须是 str 或 bytes

类型变量的主要用处是为静态类型检查器提供支持。 它们可作为泛型类型以及泛型函数和类型别名定义的形参。 请参阅 Generic 了解有关泛型类型的更多信息。 泛型函数的作用方式如下:

  1. def repeat[T](x: T, n: int) -> Sequence[T]: """Return a list containing n references to x."""
  2. return [x]*n
  3.  
  4.  
  5. def print_capitalized[S: str](x: S) -> S: """Print x capitalized, and return x."""
  6. print(x.capitalize())
  7. return x
  8.  
  9.  
  10. def concatenate[A: (str, bytes)](x: A, y: A) -> A: """Add two strings or bytes objects together."""
  11. return x + y

请注意类型变量可以为 已绑定, 已约束,或两者都不是,但不能同时为已绑定 并且 已约束。

类型变量的种类是在其通过 类型形参语法 创建时或是在传入 infer_variance=True 时由类型检查器推断得到的。 手动创建的类型变量可通过传入 covariant=Truecontravariant=True 被显式地标记为协变或逆变。 在默认情况下,手动创建的类型变量为不变。 请参阅 PEP 484 [https://peps.python.org/pep-0484/] 和 PEP 695 [https://peps.python.org/pep-0695/] 了解更多细节。

已绑定类型变量和已约束类型变量在一些重要的方面具有不同的语义。 使用 已绑定 类型变量意味着 TypeVar 将尽可能使用最专属的类型来解析:

  1. x = print_capitalized('a string')
  2. reveal_type(x) # 显示的类型是 str
  3.  
  4. class StringSubclass(str):
  5. pass
  6.  
  7. y = print_capitalized(StringSubclass('another string'))
  8. reveal_type(y) # 显示的类型是 StringSubclass
  9.  
  10. z = print_capitalized(45) # 错误:int 不是 str 的子类型

类型变量的上层绑定可以是一个具体类型、抽象类型(ABC 或 Protocol),甚至是多个类型的联合:

  1. # 可以是任何具有 __abs__ 方法的内容
  2. def print_abs[T: SupportsAbs](arg: T) -> None:
  3. print("Absolute value:", abs(arg))
  4.  
  5. U = TypeVar('U', bound=str|bytes) # 可以是联合 str|bytes 的任何子类型
  6. V = TypeVar('V', bound=SupportsAbs) # 可以是任何具有 __abs__ 方法的内容

但是,如果使用 约束 类型变量,则意味着 TypeVar 只能被解析为恰好是给定的约束之一:

  1. a = concatenate('one', 'two')
  2. reveal_type(a) # 揭示的类型为 str
  3.  
  4. b = concatenate(StringSubclass('one'), StringSubclass('two'))
  5. reveal_type(b) # 揭示的类型为 str,虽然传入的是 StringSubclass
  6.  
  7. c = concatenate('one', b'two') # 错误:在一个函数调用中类型变量 'A' 可以为 str 或 bytes,但不可同时使用

在运行时,isinstance(x, T) 将引发 TypeError

  • name
  • 类型变量的名称。

  • covariant

  • 类型变量是否已被显式地标记为 covariant。

  • contravariant

  • 类型变量是否已被显式地标记为 contravariant。

  • infer_variance

  • 类型变量的种类是否应由类型检查器来推断。

Added in version 3.12.

  • bound
  • 类型变量的上层绑定,如果有的话。

在 3.12 版本发生变更: 对于通过 类型形参语法 创建的类型变量,只有在属性被访问的时候才会对绑定求值,而不是在类型变量被创建的时候 (参见 惰性求值)。

  • constraints
  • 一个包含对类型变量的约束的元组,如果有的话。A tuple containing the constraints of the type variable, if any.

在 3.12 版本发生变更: 对于通过 类型形参语法 创建的类型变量,只有在属性被访问的时候才会对约束求值,而不是在类型变量被创建的时候 (参见 惰性求值)。

  • default
  • 类型变量的默认值,如果没有默认值,则为 typing.NoDefault

Added in version 3.13.

Added in version 3.13.

在 3.12 版本发生变更: 类型变量现在可以通过使用 PEP 695 [https://peps.python.org/pep-0695/] 引入的 类型形参 语法来声明。 增加了 infer_variance 形参。

在 3.13 版本发生变更: 增加了对默认值的支持。

  • class typing.TypeVarTuple(name, *, default=typing.NoDefault)
  • 类型变量元组。 一种启用了 variadic 泛型的专属 类型变量 形式。

类型变量元组可以通过在 类型形参列表 中使用名称前的单个星号 (*) 来声明:

  1. def move_first_element_to_last[T, *Ts](tup: tuple[T, *Ts]) -> tuple[*Ts, T]:
  2. return (*tup[1:], tup[0])

或者通过显式地唤起 TypeVarTuple 构造器:

  1. T = TypeVar("T")
  2. Ts = TypeVarTuple("Ts")
  3.  
  4. def move_first_element_to_last(tup: tuple[T, *Ts]) -> tuple[*Ts, T]:
  5. return (*tup[1:], tup[0])

一个普通类型变量将启用单个类型的形参化。 作为对比,一个类型变量元组通过将 任意 数量的类型变量封包在一个元组中来允许 任意 数量类型的形参化。 例如:

  1. # T 绑定到 int,Ts 绑定到 ()
  2. # 返回值为 (1,),其类型为 tuple[int]
  3. move_first_element_to_last(tup=(1,))
  4.  
  5. # T 绑定到 int,Ts 绑定到 (str,)
  6. # 返回值为 ('spam', 1),其类型为 tuple[str, int]
  7. move_first_element_to_last(tup=(1, 'spam'))
  8.  
  9. # T 绑定到 int,Ts 绑定到 (str, float)
  10. # 返回值为 ('spam', 3.0, 1),其类型为 tuple[str, float, int]
  11. move_first_element_to_last(tup=(1, 'spam', 3.0))
  12.  
  13. # 这不能通过类型检查(并会在运行时执行失败)
  14. # 因为 tuple[()] 与 tuple[T, *Ts] 不兼容
  15. # (至少需要有一个元素)
  16. 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]。)

类型变量元组 总是 要被解包。 这有助于区分类型变量元组和普通类型变量:

  1. x: Ts # 不可用
  2. x: tuple[Ts] # 不可用
  3. x: tuple[*Ts] # 正确的做法

类型变量元组可被用在与普通类型变量相同的上下文中。 例如,在类定义、参数和返回类型中:

  1. class Array[*Shape]:
  2. def __getitem__(self, key: tuple[*Shape]) -> float: ...
  3. def __abs__(self) -> "Array[*Shape]": ...
  4. def get_shape(self) -> tuple[*Shape]: ...

类型变量元组可以很好地与普通类型变量结合在一起:

  1. class Array[DType, *Shape]: # 这样可以
  2. pass
  3.  
  4. class Array2[*Shape, DType]: # 这样也可以
  5. pass
  6.  
  7. class Height: ...
  8. class Width: ...
  9.  
  10. float_array_1d: Array[float, Height] = Array() # 完全可以
  11. int_array_2d: Array[int, Height, Width] = Array() # 是的,同样可以

但是,请注意在一个类型参数或类型形参列表中最多只能有一个类型变量元组:

  1. x: tuple[*Ts, *Ts] # 不可用
  2. class Array[*Shape, *Shape]: # 不可用
  3. pass

最后,一个已解包的类型变量元组可以被用作 *args 的类型标注:

  1. def call_soon[*Ts](
  2. callback: Callable[[*Ts], None],
  3. *args: *Ts
  4. ) -> None:
  5. ...
  6. callback(*args)

相比非解包的 *args 标注 —— 例如 *args: int,它将指明 所有 参数均为 int —— *args: *Ts 启用了对 *args 中 单个 参数的类型的引用。 在此,这允许我们确保传入 call_soon*args 的类型与 callback 的(位置)参数的类型相匹配。

关于类型变量元组的更多细节,请参见 PEP 646 [https://peps.python.org/pep-0646/]。

  • name
  • 类型变量元组的名称。

  • default

  • 类型变量元组的默认值,如果没有默认值,则为 typing.NoDefault

Added in version 3.13.

Added in version 3.13.

Added in version 3.11.

在 3.12 版本发生变更: 类型变量元组现在可以使用 PEP 695 [https://peps.python.org/pep-0695/] 所引入的 类型形参 语法来声明。

在 3.13 版本发生变更: 增加了对默认值的支持。

  • class typing.ParamSpec(name, *, bound=None, covariant=False, contravariant=False, default=typing.NoDefault)
  • 形参专属变量。 类型变量 的一个专用版本。

In 类型形参列表,形参规格可以使用两个星号 (**) 来声明:

  1. type IntFunc[**P] = Callable[P, int]

为了保持与 Python 3.11 及更早版本的兼容性,ParamSpec 对象也可以这样创建:

  1. P = ParamSpec('P')

参数规范变量的存在主要是为了使静态类型检查器受益。 它们被用来将一个可调用对象的参数类型转发给另一个可调用对象的参数类型——这种模式通常出现在高阶函数和装饰器中。 它们只有在 Concatenate 中使用时才有效,或者作为 Callable 的第一个参数,或者作为用户定义的泛型的参数。 参见 Generic 以了解更多关于泛型的信息。

例如,为了给一个函数添加基本的日志记录,我们可以创建一个装饰器 add_logging 来记录函数调用。 参数规范变量告诉类型检查器,传入装饰器的可调用对象和由其返回的新可调用对象有相互依赖的类型参数:

  1. from collections.abc import Callable
  2. import logging
  3.  
  4. def add_logging[T, **P](f: Callable[P, T]) -> Callable[P, T]: '''A type-safe decorator to add logging to a function.'''
  5. def inner(*args: P.args, **kwargs: P.kwargs) -> T:
  6. logging.info(f'{f.__name__} was called')
  7. return f(*args, **kwargs)
  8. return inner
  9.  
  10. @add_logging
  11. def add_two(x: float, y: float) -> float: '''Add two numbers together.'''
  12. return x + y

如果没有 ParamSpec,之前标注这个的最简单方式是使用一个 TypeVar 并附带上层绑定 Callable[…, Any]。 不过这会导致两个问题:

  • 类型检查器不能对 inner 函数进行类型检查,因为 *args**kwargs 的类型必须是 Any

  • cast() 在返回 inner 函数时,可能需要在 add_logging 装饰器的主体中进行,或者必须告诉静态类型检查器忽略 return inner

  • args
  • kwargs
  • 由于 ParamSpec 同时捕获了位置参数和关键字参数,P.argsP.kwargs 可以用来将 ParamSpec 分割成其组成部分。 P.args 代表给定调用中的位置参数的元组,只能用于注释 *argsP.kwargs 代表给定调用中的关键字参数到其值的映射,只能用于注释 **kwargs。在运行时,P.argsP.kwargs 分别是 ParamSpecArgsParamSpecKwargs 的实例。

  • name

  • 形参规格的名称。

  • default

  • 形参规格的默认值,如果没有默认值,则为 typing.NoDefault

Added in version 3.13.

Added in version 3.13.

covariant=Truecontravariant=True 创建的参数规范变量可以用来声明协变或逆变泛型类型。 参数 bound 也被接受,类似于 TypeVar。 然而这些关键字的实际语义还有待决定。

Added in version 3.10.

在 3.12 版本发生变更: 形参说明现在可以使用 PEP 695 [https://peps.python.org/pep-0695/] 所引入的 类型形参 语法来声明。

在 3.13 版本发生变更: 增加了对默认值的支持。

备注

只有在全局范围内定义的参数规范变量可以被 pickle。

参见

  • typing.ParamSpecArgs
  • typing.ParamSpecKwargs
  • ParamSpec的参数和关键字参数属性。``ParamSpecP.args 属性是 ParamSpecArgs 的一个实例,P.kwargsParamSpecKwargs 的一个实例。 它们的目的是用于运行时内部检查的,对静态类型检查器没有特殊意义。

在这些对象中的任何一个上调用 get_origin() 将返回原始的 ParamSpec:

  1. >>> from typing import ParamSpec, get_origin
  2. >>> P = ParamSpec("P")
  3. >>> get_origin(P.args) is P
  4. True
  5. >>> get_origin(P.kwargs) is P
  6. True

Added in version 3.10.

  • class typing.TypeAliasType(name, value, *, type_params=())
  • 通过 type 语句创建的类型别名的类型。

示例:

  1. >>> type Alias = int
  2. >>> type(Alias)
  3. <class 'typing.TypeAliasType'>

Added in version 3.12.

  • name
  • 类型别名的名称:
  1. >>> type Alias = int
  2. >>> Alias.__name__
  3. 'Alias'
  • module
  • 类型别名定义所在的模块名称:
  1. >>> type Alias = int
  2. >>> Alias.__module__
  3. '__main__'
  • type_params
  • 类型别名的类型形参,或者如果别名不属于泛型则为一个空元组:
  1. >>> type ListOrSet[T] = list[T] | set[T]
  2. >>> ListOrSet.__type_params__
  3. (T,)
  4. >>> type NotGeneric = int
  5. >>> NotGeneric.__type_params__
  6. ()
  • value
  • 类型别名的值。 它将被 惰性求值,因此别名定义中使用的名称将直到 __value__ 属性被访问时才会被解析:
  1. >>> type Mutually = Recursive
  2. >>> type Recursive = Mutually
  3. >>> Mutually
  4. Mutually
  5. >>> Recursive
  6. Recursive
  7. >>> Mutually.__value__
  8. Recursive
  9. >>> Recursive.__value__
  10. Mutually

其他特殊指令

这些函数和类不应被直接用作标注。 它们的设计目标是作为创建和声明类型的构件。

用法:

  1. class Employee(NamedTuple):
  2. name: str
  3. id: int

这相当于:

  1. Employee = collections.namedtuple('Employee', ['name', 'id'])

为字段提供默认值,要在类体内赋值:

  1. class Employee(NamedTuple):
  2. name: str
  3. id: int = 3
  4.  
  5. employee = Employee('Guido')
  6. assert employee.id == 3

带默认值的字段必须在不带默认值的字段后面。

由此产生的类有一个额外的属性 __annotations__ ,给出一个 dict ,将字段名映射到字段类型。(字段名在 _fields 属性中,默认值在 fielddefaults 属性中,这两者都是 namedtuple() API 的一部分。)

NamedTuple 子类也支持文档字符串与方法:

  1. class Employee(NamedTuple): """代表一位雇员。"""
  2. name: str
  3. id: int = 3
  4.  
  5. def __repr__(self) -> str:
  6. return f'<Employee {self.name}, id={self.id}>'

NamedTuple 子类也可以为泛型:

  1. class Group[T](NamedTuple):
  2. key: T
  3. group: list[T]

反向兼容用法:

  1. # 在 Python 3.11 上创建通用 NamedTuple
  2. T = TypeVar("T")
  3.  
  4. class Group(NamedTuple, Generic[T]):
  5. key: T
  6. group: list[T]
  7.  
  8. # 函数语法也支持
  9. Employee = NamedTuple('Employee', [('name', str), ('id', int)])

在 3.6 版本发生变更: 添加了对 PEP 526 [https://peps.python.org/pep-0526/] 中变量注解句法的支持。

在 3.6.1 版本发生变更: 添加了对默认值、方法、文档字符串的支持。

在 3.8 版本发生变更: fieldtypes__annotations__ 属性现已使用常规字典,不再使用 OrderedDict 实例。

在 3.9 版本发生变更: 移除了 fieldtypes 属性, 改用具有相同信息,但更标准的 __annotations__ 属性。

在 3.11 版本发生变更: 添加对泛型命名元组的支持。

Deprecated since version 3.13, will be removed in version 3.15: 创建命名元组 NamedTuple 的关键字参数语法 (NT = NamedTuple("NT", x=int)) 未被写入文档且已被弃用,它将在 3.15 中被禁止。使用基于类的语法或函数式语法作为替代。

Deprecated since version 3.13, will be removed in version 3.15: 使用函数式语法创建 NamedTuple 类时,不向 'fields' 形参传值(NT = NamedTuple("NT")) 或向 'fields' 形参传递 None (NT = NamedTuple("NT", None)) 的行为已被弃用,且在 Python 3.15 中都将被禁止。要创建一个无字段的 NamedTuple 类,请使用 class NT(NamedTuple): passNT = NamedTuple("NT", [])

  • class typing.NewType(name, tp)
  • 用于创建低开销的 独有类型 的辅助类。

NewType 将被类型检查器视为一个独有类型。 但是,在运行时,调用 NewType 将原样返回其参数。

用法:

  1. UserId = NewType('UserId', int) # 声明 NewType "UserId"
  2. first_user = UserId(1) # 在运行时 "UserId" 将原样返回参数
  • module
  • 新类型定义所在的模块。

  • name

  • 新类型的名称。

  • supertype

  • 新类型所基于的类型。

Added in version 3.5.2.

在 3.10 版本发生变更: NewType 现在是一个类而不是函数。

  • class typing.Protocol(Generic)
  • 协议类的基类。

协议类是这样定义的:

  1. class Proto(Protocol):
  2. def meth(self) -> int:
  3. ...

这些类主要与静态类型检查器搭配使用,用来识别结构子类型(静态鸭子类型),例如:

  1. class C:
  2. def meth(self) -> int:
  3. return 0
  4.  
  5. def func(x: Proto) -> int:
  6. return x.meth()
  7.  
  8. func(C()) # 通过静态类型检查

请参阅 PEP 544 [https://peps.python.org/pep-0544/] 了解详情。 使用 runtime_checkable() 装饰的协议类(稍后将介绍)可作为只检查给定属性是否存在,而忽略其类型签名的简单的运行时协议。

Protocol 类可以是泛型,例如:

  1. class GenProto[T](Protocol):
  2. def meth(self) -> T:
  3. ...

在需要兼容 Python 3.11 或更早版本的代码中,可以这样编写泛型协议:

  1. T = TypeVar("T")
  2.  
  3. class GenProto(Protocol[T]):
  4. def meth(self) -> T:
  5. ...

Added in version 3.8.

  • @typing.runtime_checkable
  • 用于把 Protocol 类标记为运行时协议。

该协议可以与 isinstance()issubclass() 一起使用。应用于非协议的类时,会触发 TypeError。该指令支持简易结构检查,与 collections.abcIterable 非常类似,只擅长做一件事。 例如:

  1. @runtime_checkable
  2. class Closable(Protocol):
  3. def close(self):

  4. assert isinstance(open('somefile'), Closable)

  5. @runtime_checkable

  6. class Named(Protocol):

  7. name: str

  8. import threading

  9. assert isinstance(threading.Thread(name='Bob'), Named)

备注

runtime_checkable() 将只检查所需方法或属性是否存在,而不检查它们的类型签名或类型。 例如,ssl.SSLObject 是一个类,因此它通过了针对 Callableissubclass() 检查。 但是,ssl.SSLObject.__init__ 方法的存在只是引发 TypeError 并附带更具信息量的消息,因此它无法调用 (实例化) ssl.SSLObject

备注

针对运行时可检查协议的 isinstance() 检查相比针对非协议类的 isinstance() 检查可能会惊人的缓慢。 请考虑在性能敏感的代码中使用替代性写法如 hasattr() 调用进行结构检查。

Added in version 3.8.

在 3.12 版本发生变更: 现在 isinstance() 的内部实现对于运行时可检查协议的检查会使用 inspect.getattr_static() 来查找属性 (在之前版本中,会使用 hasattr())。 因此,在 Python 3.12+ 上一些以前被认为是运行时可检查协议的实例的对象可能不再被认为是该协议的实例,反之亦反。 大多数用户不太可能受到这一变化的影响。

在 3.12 版本发生变更: 一旦类被创建则运行时可检查协议的成员就会被视为在运行时“已冻结”。 在运行时可检查协议上打上猴子补丁属性仍然有效,但不会影响将对象与协议进行比较的 isinstance() 检查。 请参阅 "Python 3.12 有什么新变化 了解更多细节。

  • class typing.TypedDict(dict)
  • 把类型提示添加至字典的特殊构造器。在运行时,它是纯 dict

TypedDict 声明一个字典类型,该类型预期所有实例都具有一组键集,其中,每个键都与对应类型的值关联。运行时不检查此预期,而是由类型检查器强制执行。用法如下:

  1. class Point2D(TypedDict):
  2. x: int
  3. y: int
  4. label: str
  5.  
  6. a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # 可以
  7. b: Point2D = {'z': 3, 'label': 'bad'} # 不能通过类型检查
  8.  
  9. assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')

另一种创建 TypedDict 的方法是使用函数调用语法。第二个参数必须是一个 dict 字面值:

  1. Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})

这种函数式语法允许定义因为是关键字或包含连字符而不是有效 标识符 的键,例如:

  1. # 引发 SyntaxError
  2. class Point2D(TypedDict):
  3. in: int # 'in' 作为关键字
  4. x-y: int # 名称带有连字符
  5.  
  6. # 功能语法
  7. Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})

默认情况下,所有的键都必须出现在一个 TypedDict 中。 可以使用 NotRequired 将单独的键标记为非必要的:

  1. class Point2D(TypedDict):
  2. x: int
  3. y: int
  4. label: NotRequired[str]
  5.  
  6. # 替代语法
  7. Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': NotRequired[str]})

这意味着一个 Point2D TypedDict 可以省略 label 键。

也可以通过全部指定 False 将所有键都标记为默认非必要的:

  1. class Point2D(TypedDict, total=False):
  2. x: int
  3. y: int
  4.  
  5. # 替代语法
  6. Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)

这意味着一个 Point2D TypedDict 可以省略任何一个键。 类型检查器只需要支持一个字面的 FalseTrue 作为 total 参数的值。 True 是默认的,它使类主体中定义的所有项目都是必需的。

一个 total=False TypedDict 中单独的键可以使用 Required 标记为必要的:

  1. class Point2D(TypedDict, total=False):
  2. x: Required[int]
  3. y: Required[int]
  4. label: str
  5.  
  6. # 替代语法
  7. Point2D = TypedDict('Point2D', {
  8. 'x': Required[int],
  9. 'y': Required[int],
  10. 'label': str
  11. }, total=False)

一个 TypedDict 类型有可能使用基于类的语法从一个或多个其他 TypedDict 类型继承。用法:

  1. class Point3D(Point2D):
  2. z: int

Point3D 有三个项目 : x , yz 。 其等价于定义:

  1. class Point3D(TypedDict):
  2. x: int
  3. y: int
  4. z: int

TypedDict 不能从非 TypedDict 类继承,除了 Generic。 例如:

  1. class X(TypedDict):
  2. x: int
  3.  
  4. class Y(TypedDict):
  5. y: int
  6.  
  7. class Z(object): pass # 非 TypedDict 类
  8.  
  9. class XY(X, Y): pass # 可以
  10.  
  11. class XZ(X, Z): pass # 引发 TypeError

TypedDict 也可以为泛型的:

  1. class Group[T](TypedDict):
  2. key: T
  3. group: list[T]

要创建与 Python 3.11 或更低版本兼容的泛型 TypedDict,请显式地从 Generic 继承:

  1. T = TypeVar("T")
  2.  
  3. class Group(TypedDict, Generic[T]):
  4. key: T
  5. group: list[T]

TypedDict 可以通过注解字典(参见 注解最佳实践 了解更多关于注解的最佳实践)、 __total____required_keys____optional_keys__ 进行内省。

  • total
  • Point2D.__total__ 给出了 total 参数的值。 例如:
  1. >>> from typing import TypedDict
  2. >>> class Point2D(TypedDict): pass
  3. >>> Point2D.__total__
  4. True
  5. >>> class Point2D(TypedDict, total=False): pass
  6. >>> Point2D.__total__
  7. False
  8. >>> class Point3D(Point2D): pass
  9. >>> Point3D.__total__
  10. True

该属性 只 反映传给当前 TypedDict 类的 total 参数的值,而不反映这个类在语义上是否完整。 例如,一个 __total__ 被设为 TrueTypedDict 可能有用 NotRequired 标记的键,或者它可能继承自另一个设置了 total=FalseTypedDict。 因此,使用 __required_keys____optional_keys__ 进行内省通常会更好。

  • required_keys

Added in version 3.9.

  • optional_keys
  • Point2D.__required_keys__Point2D.__optional_keys__ 返回分别包含必要的和非必要的键的 frozenset 对象。

标记为 Required 的键总是会出现在 __required_keys__ 中而标记为 NotRequired 的键总是会出现在 __optional_keys__ 中。

为了向下兼容 Python 3.10 及更老的版本,还可以使用继承机制在同一个 TypedDict 中同时声明必要和非必要的键。 这是通过声明一个具有 total 参数值的 TypedDict 然后在另一个 TypedDict 中继承它并使用不同的 total 值来实现的:

  1. >>> class Point2D(TypedDict, total=False):
  2. ... x: int
  3. ... y: int
  4. ...
  5. >>> class Point3D(Point2D):
  6. ... z: int
  7. ...
  8. >>> Point3D.__required_keys__ == frozenset({'z'})
  9. True
  10. >>> Point3D.__optional_keys__ == frozenset({'x', 'y'})
  11. True

Added in version 3.9.

备注

如果使用了 from __future__ import annotations 或者如果以字符串形式给出标注,那么标注不会在定义 TypedDict 时被求值。 因此,__required_keys____optional_keys__ 所依赖的运行时内省可能无法正常工作,这些属性的值也可能不正确。

ReadOnly 的支持反映在下列属性中:

  • readonly_keys
  • 一个包含所有只读键名称的 frozenset。 带有 ReadOnly 限定符的键被认为是只读的。

Added in version 3.13.

  • mutable_keys
  • 一个包含所有可变键名称的 frozenset。 不带有 ReadOnly 限定符的键被认为是可变的。

Added in version 3.13.

更多示例与 TypedDict 的详细规则,详见 PEP 589 [https://peps.python.org/pep-0589/]。

Added in version 3.8.

在 3.11 版本发生变更: 增加了对将单独的键标记为 RequiredNotRequired 的支持。 参见 PEP 655 [https://peps.python.org/pep-0655/]。

在 3.11 版本发生变更: 添加对泛型 TypedDict 的支持。

在 3.13 版本发生变更: 移除了对使用关键字参数方法创建 TypedDict 的支持。

在 3.13 版本发生变更: 添加了对 ReadOnly 限定符的支持。

Deprecated since version 3.13, will be removed in version 3.15: 使用函数式语法创建 TypedDict 类时,不向 'fields' 形参传值(TD = TypedDict("TD")) 或向 'fields' 形参传递 None (TD = TypedDict ("TD", None)) 的行为已被弃用,且在 Python 3.15 中都将被禁止。要创建一个无字段的 TypedDict 类,请使用 class TD(TypedDict ): passTD = TypedDict ("TD", {})

协议

下列协议由 typing 模块提供并已全被装饰为 可在运行时检查的

  • class typing.SupportsAbs
  • 一个抽象基类,含一个抽象方法 __abs__,该方法与其返回类型协变。
  • class typing.SupportsBytes
  • 一个抽象基类,含一个抽象方法 __bytes__
  • class typing.SupportsComplex
  • 一个抽象基类,含一个抽象方法 __complex__
  • class typing.SupportsFloat
  • 一个抽象基类,含一个抽象方法 __float__
  • class typing.SupportsIndex
  • 一个抽象基类,含一个抽象方法 __index__

Added in version 3.8.

  • class typing.SupportsInt
  • 一个抽象基类,含一个抽象方法 __int__
  • class typing.SupportsRound
  • 一个抽象基类,含一个抽象方法 __round__,该方法与其返回类型协变。

与 IO 相关的抽象基类

  • 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() 的调用时,如果该值不是指定的类型则会报错:

  1. def greet(name: str) -> None:
  2. assert_type(name, str) # OK,推断 `name` 的类型是 `str`
  3. assert_type(name, int) # 类型检查器错误

此函数适用于确保类型检查器对脚本的理解符合开发者的意图:

  1. def complex_function(arg: object):
  2. # 执行某些复杂的类型细化逻辑,
  3. # 在此之后我们希望推断出的类型为 `int`
  4. ...
  5. # 测试类型检查器能否正确理解我们的函数
  6. assert_type(arg, int)

Added in version 3.11.

  • typing.assert_never(arg, /)
  • 让静态类型检查器确认一行代码是不可达的。

示例:

  1. def int_or_str(arg: int | str) -> None:
  2. match arg:
  3. case int():
  4. print("It's an int")
  5. case str():
  6. print("It's a str")
  7. case _ as unreachable:
  8. assert_never(unreachable)

在这里,标注允许类型检查器推断最后一种情况永远不会执行,因为 arg 要么是 int 要么是 str,而这两种选项都已被之前的情况覆盖了。

如果类型检查器发现对 assert_never() 的调用是可达的,它将报告一个错误。 举例来说,如果 arg 的类型标注改为 int | str | float,则类型检查器将报告一个错误指出 unreachablefloat 类型。 对于通过类型检查的 assert_never 调用,参数传入的推断类型必须为兜底类型 Never,而不能为任何其他类型。

在运行时,如果调用此函数将抛出一个异常。

参见

Unreachable Code and Exhaustiveness Checking [https://typing.readthedocs.io/en/latest/guides/unreachable.html] 提供了更多关于静态类型穷举检查的信息。

Added in version 3.11.

  • typing.reveal_type(obj, /)
  • 让静态类型检查器显示推测的表达式类型。

当静态类型检查器遇到一个对此函数的调用时,它将发出带有所推测参数类型的诊断信息。 例如:

  1. x: int = 1
  2. reveal_type(x) # 揭示的类型为 "builtins.int"

这在你想要调试你的类型检查器如何处理一段特定代码时很有用处。

在运行时,此函数会将其参数类型打印到 sys.stderr 并不加修改地返回该参数 (以允许该调用在表达式中使用):

  1. x = reveal_type(1) # 打印 "Runtime type is int"
  2. print(x) # 打印 "1"

请注意在运行时类型可能不同于类型静态检查器所推测的类型(明确程度可能更高也可能更低)。

大多数类型检查器都能在任何地方支持 reveal_type(),即使并未从 typing 导入该名称。 不过,从 typing 导入该名称将允许你的代码在运行时不会出现运行时错误并能更清晰地传递意图。

Added in version 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 的方式来转换类的运行时“魔法”。

装饰器函数使用方式的例子:

  1. @dataclass_transform()
  2. def create_modelT -> type[T]:
  3. return cls

  4. @create_model

  5. class CustomerModel:

  6. id: int

  7. name: str

在基类上:

  1. @dataclass_transform()
  2. class ModelBase:

  3. class CustomerModel(ModelBase):

  4. id: int

  5. name: str

在元类上:

  1. @dataclass_transform()
  2. class ModelMeta(type):

  3. class ModelBase(metaclass=ModelMeta):

  4. class CustomerModel(ModelBase):

  5. id: int

  6. name: str

上面定义的 CustomerModel 类将被类型检查器视为类似于使用 @dataclasses.dataclass 创建的类。 例如,类型检查器将假定这些类具有接受 idname__init__ 方法。

被装饰的类、元类或函数可以接受以下布尔值参数,类型检查器将假定它们具有与 @dataclasses.dataclass 装饰器相同的效果: init, eq, order, unsafe_hash, frozen, match_args, kw_onlyslots。 这些参数的值 (TrueFalse) 必须可以被静态地求值。

传给 dataclass_transform 装饰器的参数可以被用来定制被装饰的类、元类或函数的默认行为:

  • 参数:
    • eq_default (bool) — 指明如果调用方省略了 eq 形参则应将其假定为 True 还是 False。 默认为 True

    • order_default (bool) — 指明如果调用方省略了 order 形参则应将其假定为 True 还是 False。 默认为 False

    • kw_only_default (bool) — 指明如果调用方省略了 kw_only 形参则应将其假定为 True 还是 False。 默认为 False

    • frozen_default (bool) — 指明如果调用方省略了 frozen 形参则应将其假定为 True 还是 False。 默认为 False。 .. versionadded:: 3.12

    • field_specifiers (tuple[Callable[…, Any], …]) — 指定一个受支持的类或描述字段的函数的静态列表,类似于 dataclasses.field()。 默认为 ()

    • **kwargs (Any) — 接受任何其他关键字以便允许可能的未来扩展。

类型检查器能识别下列字段设定器的可选形参:

字段设定器的可识别形参
形参名称

描述

init

指明字段是否应当被包括在合成的 __init__ 方法中。 如果未指明,则 init 默认为 True

default

为字段提供默认值。

default_factory

提供一个返回字段默认值的运行时回调。 如果 defaultdefault_factory 均未指定,则会假定字段没有默认值而在类被实例化时必须提供一个值。

factory

字段说明符上 default_factory 形参的别名。

kw_only

指明字段是否应被标记为仅限关键字的。 如为 True,字段将是仅限关键字的。 如为 False,它将不是仅限关键字的。 如未指明,则将使用以 dataclass_transform 装饰的对象的 kw_only 形参的值,或者如果该值也未指明,则将使用 dataclass_transformkw_only_default 的值。

alias

提供字段的替代名称。 该替代名称会被用于合成的 __init__ 方法。

在运行时,该装饰器会将其参数记录到被装饰对象的 __dataclass_transform__ 属性。 它没有其他的运行时影响。

更多细节请参见 PEP 681 [https://peps.python.org/pep-0681/]。

Added in version 3.11.

  • @typing.overload
  • 用于创建重载函数和方法的装饰器。

@overload 装饰器允许描述支持多参数类型不同组合的函数和方法。 一系列以 @overload 装饰的定义必须带上恰好一个非 @overload 装饰的定义(用于同一个函数/方法)。

@overload 装饰的定义仅对类型检查器有用,因为它们将被非 @overload 装饰的定义覆盖。 与此同时,非 @overload 装饰的定义将在运行时使用但应被类型检查器忽略。 在运行时,直接调用以 @overload 装饰的函数将引发 NotImplementedError

一个提供了比使用联合或类型变量更精确的类型的重载的示例:

  1. @overload
  2. def process(response: None) -> None:
  3. @overload
  4. def process(response: int) -> tuple[int, str]:
  5. @overload
  6. def process(response: bytes) -> str:
  7. def process(response):
  8. # 以下为真正的实现

请参阅 PEP 484 [https://peps.python.org/pep-0484/] 了解更多细节以及与其他类型语义的比较。

在 3.11 版本发生变更: 现在可以使用 get_overloads() 在运行时内省有重载的函数。

  • typing.get_overloads(func)
  • 为 func 返回以 @overload 装饰的定义的序列。

func 是用于实现过载函数的函数对象。 例如,根据文档中为 @overload 给出的 process 定义,get_overloads(process) 将为所定义的三个过载函数返回由三个函数对象组成的序列。 如果在不带过载的函数上调用,get_overloads() 将返回一个空序列。

get_overloads() 可被用来在运行时内省一个过载函数。

Added in version 3.11.

  • typing.clear_overloads()
  • 清空内部注册表中所有已注册的重载。

这可用于回收注册表所使用的内存。

Added in version 3.11.

  • @typing.final
  • 表示最终化方法和最终化类的装饰器。

@final 装饰一个方法将向类型检查器指明该方法不可在子类中被重载。 以 @final 装饰一个类表示它不可被子类化。

例如:

  1. class Base:
  2. @final
  3. def done(self) -> None:
  4. ...
  5. class Sub(Base):
  6. def done(self) -> None: # 类型检查器报告错误
  7. ...
  8.  
  9. @final
  10. class Leaf:
  11. ...
  12. class Other(Leaf): # 类型检查器报告错误
  13. ...

这些属性没有运行时检查。详见 PEP 591 [https://peps.python.org/pep-0591/]。

Added in version 3.8.

在 3.11 版本发生变更: 该装饰器现在将尝试在被装饰的对象上设置 __final__ 属性为 True。 这样,可以在运行时使用 if getattr(obj, "__final__", False) 这样的检查来确定对象 obj 是否已被标记为终结。 如果被装饰的对象不支持设置属性,该装饰器将不加修改地返回对象而不会引发异常。

  • @typing.no_type_check
  • 标明注解不是类型提示的装饰器。

此作用方式类似于类或函数的 decorator。 对于类,它将递归地应用到该类中定义的所有方法和类(但不包括在其超类或子类中定义的方法)。 类型检查器将忽略带有此装饰器的函数或类的所有标注。

@no_type_check 将原地改变被装饰的对象。

  • @typing.no_type_check_decorator
  • 让其他装饰器具有 no_type_check() 效果的装饰器。

本装饰器用 no_type_check() 里的装饰函数打包其他装饰器。

Deprecated since version 3.13, will be removed in version 3.15: @no_type_check_decorator 没有任何类型检查器支持过,所以它被弃用,并将在 Python 3.15 中被移除。

  • @typing.override
  • 该装饰器指明子类中的某个方法是重载超类中的方法或属性。

如果一个以 @override 装饰的方法实际未重载任何东西则类型检查器应当报告错误。 这有助于防止当基类发生修改而子类未进行相应修改而导致的问题。

例如:

  1. class Base:
  2. def log_status(self) -> None:
  3. ...
  4.  
  5. class Sub(Base):
  6. @override
  7. def log_status(self) -> None: # 可以:重写 Base.log_status
  8. ...
  9.  
  10. @override
  11. def done(self) -> None: # 类型检查器报告错误
  12. ...

没有对此特征属性的运行时检查。

该装饰器将尝试在被装饰的对象上设置 __override__ 属性为 True。 这样,可以在运行时使用 if getattr(obj, "__override__", False) 这样的检查来确定对象 obj 是否已被标记为重载。 如果被装饰的对象不支持设置属性,该装饰器将不加修改地返回对象而不会引发异常。

更多细节参见 PEP 698 [https://peps.python.org/pep-0698/]。

Added in version 3.12.

  • @typing.type_check_only
  • 将类或函数标记为在运行时不可用的装饰器。

在运行时,该装饰器本身不可用。实现返回的是私有类实例时,它主要是用于标记在类型存根文件中定义的类。

  1. @type_check_only
  2. class Response: # 私有或在运行时不可用
  3. code: int
  4. def get_header(self, name: str) -> str:

  5. def fetch_response() -> Response:

注意,建议不要返回私有类实例,最好将之设为公共类。

内省辅助器

  • typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)
  • 返回函数、方法、模块、类对象的类型提示的字典。

该函数通常与 obj.__annotations__ 相同,但会对注解字典进行以下更改:

  • 以字符串字面形式或 ForwardRef 对象编码的前向引用会在 globalns, localns 和 (如适用) obj 的 类型形参 命名空间中求值。如果没有传入 globalns 或 localns,则会从 obj 中推断出适当的命名空间字典。

  • None 被替换为 types.NoneType

  • 如果在 obj 上应用了 @no_type_check,返回一个空字典。

  • 如果 obj 是一个类 C,则函数返回一个合并了 C 的基类与 C 上的基类的字典。 这是通过遍历 C.__mro__ 并迭代地合并 __annotations__ 字典来实现的。 在 method resolution order 中较早出现的类上的标注总是会优先于在方法解析顺序中较晚出现的类的标注。

  • 除非 include_extras 设置为 True,否则函数会递归地将所有出现的 Annotated[T, …] 替换为 T (详见 Annotated)。

另请参阅 inspect.get_annotations(),这是一个以更直接方式返回注解的低级函数。

备注

如果 obj 注解中的任何前向引用不可解析或不是有效的 Python 代码,此函数将引发 NameError 等异常。例如导入的 类型别名 包含正向引用,或名称在 if TYPE_CHECKING 下导入。

在 3.9 版本发生变更: 增加了作为 PEP 593 [https://peps.python.org/pep-0593/] 组成部分的 include_extras 形参。 请参阅 Annotated 文档了解详情。

在 3.11 版本发生变更: 在之前,如果设置了等于 None 的默认值则会为函数和方法标注添加 Optional[t]。 现在标注将被不加修改地返回。

  • typing.get_origin(tp)
  • 获取一个类型的不带下标的版本:对于 X[Y, Z, …] 形式的类型对象将返回 X

如果 X 是一个内置类型或 collections 类在 typing 模块中的别名,它将被正规化为原始的类。 如果 XParamSpecArgsParamSpecKwargs 的实例,则返回下层的 ParamSpec。 对于不受支持的对象将返回 None

示例:

  1. assert get_origin(str) is None
  2. assert get_origin(Dict[str, int]) is dict
  3. assert get_origin(Union[int, str]) is Union
  4. assert get_origin(Annotated[str, "metadata"]) is Annotated
  5. P = ParamSpec('P')
  6. assert get_origin(P.args) is P
  7. assert get_origin(P.kwargs) is P

Added in version 3.8.

  • typing.get_args(tp)
  • 获取已执行所有下标的类型参数:对于 X[Y, Z, …] 形式的类型对象将返回 (Y, Z, …)

如果 X 是一个并集或是包含在另一个泛型类型中的 Literal,则 (Y, Z, …) 的顺序可能因类型缓存而与原始参数 [Y, Z, …] 存在差异。 对于不受支持的对象将返回 ()

示例:

  1. assert get_args(int) == ()
  2. assert get_args(Dict[int, str]) == (int, str)
  3. assert get_args(Union[int, str]) == (int, str)

Added in version 3.8.

  • typing.get_protocol_members(tp)
  • 返回 Protocol 中定义的成员构成的集合。
  1. >>> from typing import Protocol, get_protocol_members
  2. >>> class P(Protocol):
  3. ... def a(self) -> str: ...
  4. ... b: int
  5. >>> get_protocol_members(P) == frozenset({'a', 'b'})
  6. True

如果参数不是协议,引发 TypeError

Added in version 3.13.

  • typing.is_protocol(tp)
  • 检查一个类型是否为 Protocol

例如:

  1. class P(Protocol):
  2. def a(self) -> str: ...
  3. b: int
  4.  
  5. is_protocol(P) # => True
  6. is_protocol(int) # => False

Added in version 3.13.

  • typing.is_typeddict(tp)
  • 检查一个类型是否为 TypedDict

例如:

  1. class Film(TypedDict):
  2. title: str
  3. year: int
  4.  
  5. assert is_typeddict(Film)
  6. assert not is_typeddict(list | str)
  7.  
  8. # TypedDict 是创建类型化字典的工厂,
  9. # 不是类型化字典
  10. assert not is_typeddict(TypedDict)

Added in version 3.10.

  • class typing.ForwardRef
  • 用于字符串前向引用的内部类型表示的类。

例如,List["SomeClass"] 会被隐式转换为 List[ForwardRef("SomeClass")]ForwardRef 不应由用户来实例化,但可以由内省工具使用。

备注

PEP 585 [https://peps.python.org/pep-0585/] 泛型类型例如 list["SomeClass"] 将不会被隐式地转换为 list[ForwardRef("SomeClass")] 因而将不会自动解析为 list[SomeClass]

Added in version 3.7.4.

  • typing.NoDefault
  • 一个用于指示类型形参没有默认值的哨兵对象。例如:
  1. >>> T = TypeVar("T")
  2. >>> T.__default__ is typing.NoDefault
  3. True
  4. >>> S = TypeVar("S", default=None)
  5. >>> S.__default__ is None
  6. True

Added in version 3.13.

常量

  • typing.TYPE_CHECKING
  • 会被第 3 方静态类型检查器假定为 True 的特殊常量。 在运行时将为 False

用法:

  1. if TYPE_CHECKING:
  2. import expensive_mod
  3.  
  4. def fun(arg: 'expensive_mod.SomeType') -> None:
  5. local_var: expensive_mod.AnotherType = other_fun()

第一个类型注解必须用引号标注,才能把它当作“前向引用”,从而在解释器运行时中隐藏 expensive_mod 引用。局部变量的类型注释不会被评估,因此,第二个注解不需要用引号引起来。

备注

若用了 from __future__ import annotations,函数定义时则不求值注解,直接把注解以字符串形式存在 __annotations__ 里。这时毋需为注解打引号(见 PEP 563 [https://peps.python.org/pep-0563/])。

Added in version 3.5.2.

一些已被弃用的别名

本模块给标准库中已有的类定义了许多别名,这些别名现已不再建议使用。起初 typing 模块包含这些别名是为了支持用 [] 来参数化泛型类。然而,在 Python 3.9 中,对应的已有的类也支持了 [] (参见 PEP 585 [https://peps.python.org/pep-0585/]),因此这些别名了就成了多余的了。

这些多余的类型从 Python 3.9 起被弃用。然而,虽然它们可能会在某一时刻被移除,但目前还没有移除它们的计划。因此,解释器目前不会对这些别名发出弃用警告。

一旦确定了何时这些别名将被移除,解释器将比正式移除之时提前至少两个版本发出弃用警告 (deprecation warning)。但保证至少在 Python 3.14 之前,这些别名仍会留在 typing 模块中,并且不会引发弃用警告。

如果被类型检查器检查的程序旨在运行于 Python 3.9 或更高版本,则鼓励类型检查器标记出这些不建议使用的类型。

内置类型的别名

  • class typing.Dict(dict, MutableMapping[KT, VT])
  • dict 的已弃用的别名。

请注意,注释参数时,最好使用抽象的多项集类型,如 Mapping,而不是使用 dicttyping.Dict

自 3.9 版本弃用: builtins.dict 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

  • class typing.List(list, MutableSequence[T])
  • list 的已弃用的别名。

请注意,注释参数时,最好使用抽象的多项集类型,如 SequenceIterable,而不是使用 listtyping.List

自 3.9 版本弃用: builtins.list 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

  • class typing.Set(set, MutableSet[T])
  • builtins.set 的已弃用的别名。

请注意,注释参数时,最好使用抽象的多项集类型,如 collections.abc.Set,而不是使用 settyping.Set

自 3.9 版本弃用: builtins.set 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

  • class typing.FrozenSet(frozenset, AbstractSet[T_co])
  • builtins.frozenset 的已弃用的别名。

自 3.9 版本弃用: builtins.frozenset 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

  • typing.Tuple
  • tuple 的已弃用的别名。

tupleTuple 是类型系统中的特例;更多详细信息请参见 标注元组

自 3.9 版本弃用: builtins.tuple 现在支持下标操作([])。参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

  • class typing.Type(Generic[CT_co])
  • type 的已弃用的别名。

有关在类型注解中使用 typetyping.Type 的详细信息,请参阅 类对象的类型

Added in version 3.5.2.

自 3.9 版本弃用: builtins.type 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

collections 中的类型的别名。

  • class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])
  • collections.defaultdict 的已弃用的别名。

Added in version 3.5.2.

自 3.9 版本弃用: collections.defaultdict 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

  • class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])
  • collections.OrderedDict 的已弃用的别名。

Added in version 3.7.2.

自 3.9 版本弃用: collections.OrderedDict 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

  • class typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT])
  • collections.ChainMap 的已弃用的别名。

Added in version 3.6.1.

自 3.9 版本弃用: collections.ChainMap 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

  • class typing.Counter(collections.Counter, Dict[T, int])
  • collections.Counter 的已弃用的别名。

Added in version 3.6.1.

自 3.9 版本弃用: collections.Counter 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

  • class typing.Deque(deque, MutableSequence[T])
  • collections.deque 的已弃用的别名。

Added in version 3.6.1.

自 3.9 版本弃用: collections.deque 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

其他具体类型的别名

这些类型(与对应的函数)是 AnyStr 上的泛型。 Pattern 可以被特化为 Pattern[str]Pattern[bytes]Match 可以被特化为 Match[str]Match[bytes]

自 3.9 版本弃用: re 模块中的 PatternMatch 类现已支持 []。详见 PEP 585 [https://peps.python.org/pep-0585/] 与 GenericAlias 类型

  • class typing.Text
  • str 的已弃用的别名。

Text 被用来为 Python 2 代码提供向上兼容的路径:在 Python 2 中,Textunicode 的别名。

使用 Text 时,值中必须包含 unicode 字符串,以兼容 Python 2 和 Python 3:

  1. def add_unicode_checkmark(text: Text) -> Text:
  2. return text + u' \u2713'

Added in version 3.5.2.

自 3.11 版本弃用: Python 2 已不再受支持,并且大部分类型检查器也都不再支持 Python 2 代码的类型检查。 目前还没有计划移除该别名,但建议用户使用 str 来代替 Text

collections.abc 中容器 ABC 的别名

自 3.9 版本弃用: collections.abc.Set 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

Deprecated since version 3.9, will be removed in version 3.14: 首选 collections.abc.Buffer,或是 bytes | bytearray | memoryview 这样的并集。

Added in version 3.6.

自 3.9 版本弃用: collections.abc.Collection 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.Container 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.ItemsView 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.KeysView 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.Mapping 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.MappingView 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.MutableMapping 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.MutableSequence 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.MutableSet 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.Sequence 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.ValuesView 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

collections.abc 中异步 ABC 的别名

  • class typing.Coroutine(Awaitable[ReturnType], Generic[YieldType, SendType, ReturnType])
  • collections.abc.Coroutine 的已弃用的别名。

有关在注解类型中使用 collections.abc.Coroutinetyping.Coroutine 的详细信息,请参见 标注生成器和协程

Added in version 3.5.3.

自 3.9 版本弃用: collections.abc.Coroutine 现在支持下标操作([])。参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

有关在注解类型中使用 collections.abc.AsyncGeneratortyping.AsyncGenerator 的详细信息,请参见 标注生成器和协程

Added in version 3.6.1.

自 3.9 版本弃用: collections.abc.AsyncGenerator 现在支持下标操作([])。参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

在 3.13 版本发生变更: SendType 形参现在有默认值。

Added in version 3.5.2.

自 3.9 版本弃用: collections.abc.AsyncIterable 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

Added in version 3.5.2.

自 3.9 版本弃用: collections.abc.AsyncIterator 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

Added in version 3.5.2.

自 3.9 版本弃用: collections.abc.Awaitable 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

collections.abc 中其他 ABC 的别名

自 3.9 版本弃用: collections.abc.Iterable 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.9 版本弃用: collections.abc.Iterator 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

有关如何在类型标注中使用 collections.abc.Callabletyping.Callable 的详细信息请参阅 标注可调用对象

自 3.9 版本弃用: collections.abc.Callable 现在支持下标操作([])。参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

在 3.10 版本发生变更: Callable 现在支持 ParamSpecConcatenate。 详情见 PEP 612 [https://peps.python.org/pep-0612/]。

  • class typing.Generator(Iterator[YieldType], Generic[YieldType, SendType, ReturnType])
  • collections.abc.Generator 的已弃用的别名。

有关在注解类型中使用 collections.abc.Generatortyping.Generator 的详细信息,请参见 标注生成器和协程

自 3.9 版本弃用: collections.abc.Generator 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

在 3.13 版本发生变更: 添加了发送和返回类型的默认值。

自 3.12 版本弃用: 请改为直接使用 collections.abc.Hashable

自 3.9 版本弃用: collections.abc.Reversible 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

自 3.12 版本弃用: 请改为直接使用 collections.abc.Sized

contextlib ABC 的别名

第一个类型形参 T_co 表示 __enter__() 方法返回值的类型。可选的第二个类型形参 ExitT_co 默认为 bool | None,它表示 __exit__() 方法返回的类型。

Added in version 3.5.4.

自 3.9 版本弃用: contextlib.AbstractContextManager 现在支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

在 3.13 版本发生变更: 添加了可选的第二个类型形参,ExitT_co

第一个类型形参 T_co 表示 __aenter__() 方法返回值的类型。可选的第二个类型形参 AExitT_co 默认为 bool | None,它表示 __aexit__() 方法返回的类型。

Added in version 3.6.2.

自 3.9 版本弃用: contextlib.AbstractAsyncContextManager 现在 支持下标操作 ([])。 参见 PEP 585 [https://peps.python.org/pep-0585/] 和 GenericAlias 类型

在 3.13 版本发生变更: 添加了可选的第二个类型形参,AExitT_co

主要特性的弃用时间线

typing 的某些特性被弃用,并且可能在将来的 Python 版本中被移除。下表总结了主要的弃用特性。该表可能会被更改,而且并没有列出所有的弃用特性。

特性 弃用于 计划移除 PEP/问题
标准容器的 typing 版本 3.9 未定(请参阅 一些已被弃用的别名 了解详情) PEP 585 [https://peps.python.org/pep-0585/]
typing.ByteString 3.9 3.14 gh-91896 [https://github.com/python/cpython/issues/91896]
typing.Text 3.11 未确定 gh-92332 [https://github.com/python/cpython/issues/92332]
typing.Hashabletyping.Sized 3.12 未确定 gh-94309 [https://github.com/python/cpython/issues/94309]
typing.TypeAlias 3.12 未确定 PEP 695 [https://peps.python.org/pep-0695/]
@typing.no_type_check_decorator 3.13 3.15 gh-106309 [https://github.com/python/cpython/issues/106309]
typing.AnyStr 3.13 3.18 gh-105578 [https://github.com/python/cpython/issues/105578]