typing
— 类型提示支持¶
在 3.5 版本加入。
源代码: Lib/typing.py
备注
Python 运行时不强制函数和变量类型注解。它们可以被第三方工具使用,例如类型检查器、IDE、linter 等。
本模块为类型提示提供运行时支持。
考虑下面的函数
def surface_area_of_cube(edge_length: float) -> str:
return f"The surface area of the cube is {6 * edge_length ** 2}."
函数 surface_area_of_cube
接受一个预期为 float
实例的参数,如类型提示 edge_length: float
所示。该函数预期返回一个 str
实例,如 -> str
提示所示。
虽然类型提示可以是简单的类,如 float
或 str
,但它们也可以更复杂。typing
模块提供了更高级的类型提示词汇表。
typing
模块经常添加新功能。typing_extensions 包为旧版本的 Python 提供了这些新功能的向后移植。
参见
- 类型提示速查表
类型提示的快速概览(托管在 mypy 文档中)
- mypy 文档的类型系统参考部分
Python 类型系统通过 PEPs 进行标准化,因此本参考资料应广泛适用于大多数 Python 类型检查器。(某些部分可能仍然特定于 mypy。)
- Python 静态类型
由社区编写的与类型检查器无关的文档,详细介绍了类型系统功能、有用的类型相关工具和类型提示最佳实践。
Python 类型系统规范¶
Python 类型系统的规范(规范、最新)可在Python 类型系统规范中找到。
类型别名¶
类型别名使用 type
语句定义,该语句创建 TypeAliasType
的实例。在此示例中,Vector
和 list[float]
将被静态类型检查器同等对待。
type Vector = list[float]
def scale(scalar: float, vector: Vector) -> Vector:
return [scalar * num for num in vector]
# passes type checking; a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])
类型别名对于简化复杂的类型签名非常有用。例如
from collections.abc import Sequence
type ConnectionOptions = dict[str, str]
type Address = tuple[str, int]
type Server = tuple[Address, ConnectionOptions]
def broadcast_message(message: str, servers: Sequence[Server]) -> None:
...
# The static type checker will treat the previous type signature as
# being exactly equivalent to this one.
def broadcast_message(
message: str,
servers: Sequence[tuple[tuple[str, int], dict[str, str]]]
) -> None:
...
type
语句是 Python 3.12 中的新功能。为了向后兼容,类型别名也可以通过简单赋值创建
Vector = list[float]
或者用 TypeAlias
标记,以明确这是一个类型别名,而不是一个普通变量赋值。
from typing import TypeAlias
Vector: TypeAlias = list[float]
NewType¶
使用 NewType
辅助函数创建不同的类型
from typing import NewType
UserId = NewType('UserId', int)
some_id = UserId(524313)
静态类型检查器会将新类型视为原始类型的子类。这有助于捕获逻辑错误
def get_user_name(user_id: UserId) -> str:
...
# passes type checking
user_a = get_user_name(UserId(42351))
# fails type checking; an int is not a UserId
user_b = get_user_name(-1)
您仍然可以在 UserId
类型的变量上执行所有 int
操作,但结果始终是 int
类型。这允许您在预期 int
的任何地方传入 UserId
,但会阻止您以无效方式意外创建 UserId
。
# 'output' is of type 'int', not 'UserId'
output = UserId(23413) + UserId(54341)
请注意,这些检查仅由静态类型检查器强制执行。在运行时,语句 Derived = NewType('Derived', Base)
将使 Derived
成为一个可调用对象,它会立即返回您传入的任何参数。这意味着表达式 Derived(some_value)
不会创建新类,也不会引入超出常规函数调用的大量开销。
更准确地说,表达式 some_value is Derived(some_value)
在运行时始终为真。
创建 Derived
的子类型是无效的
from typing import NewType
UserId = NewType('UserId', int)
# Fails at runtime and does not pass type checking
class AdminUserId(UserId): pass
但是,可以基于“派生”的 NewType
创建 NewType
from typing import NewType
UserId = NewType('UserId', int)
ProUserId = NewType('ProUserId', UserId)
并且 ProUserId
的类型检查将按预期工作。
有关更多详细信息,请参阅 PEP 484。
备注
回想一下,使用类型别名声明了两个类型是 等价的 。执行 type Alias = Original
将使静态类型检查器在所有情况下都将 Alias
视为与 Original
完全等价 。当您想简化复杂的类型签名时,这很有用。
相反,NewType
声明了一个类型是另一个类型的 子类型 。执行 Derived = NewType('Derived', Original)
将使静态类型检查器将 Derived
视为 Original
的 子类 ,这意味着类型为 Original
的值不能用于预期类型为 Derived
的位置。当您想以最小的运行时成本防止逻辑错误时,这很有用。
3.5.2 版本新增。
3.10 版本中的更改: NewType
现在是一个类而不是一个函数。因此,与常规函数调用相比,调用 NewType
会产生一些额外的运行时成本。
3.11 版本中的更改: 调用 NewType
的性能已恢复到 Python 3.9 的水平。
注解可调用对象¶
函数——或其他可调用对象——可以使用 collections.abc.Callable
或已弃用的 typing.Callable
进行注解。Callable[[int], str]
表示一个接受一个 int
类型的参数并返回 str
的函数。
例如:
from collections.abc import Callable, Awaitable
def feeder(get_next_item: Callable[[], str]) -> None:
... # Body
def async_query(on_success: Callable[[int], None],
on_error: Callable[[int, Exception], None]) -> None:
... # Body
async def on_update(value: str) -> None:
... # Body
callback: Callable[[str], Awaitable[None]] = on_update
订阅语法必须始终与恰好两个值一起使用:参数列表和返回类型。参数列表必须是类型列表、ParamSpec
、Concatenate
或省略号(...
)。返回类型必须是单个类型。
如果参数列表给定字面省略号 ...
,则表示接受具有任意参数列表的可调用对象。
def concat(x: str, y: str) -> str:
return x + y
x: Callable[..., str]
x = str # OK
x = concat # Also OK
Callable
无法表达复杂的签名,例如接受可变数量参数的函数、重载函数或具有仅关键字参数的函数。但是,可以通过定义具有 __call__()
方法的 Protocol
类来表达这些签名
from collections.abc import Iterable
from typing import Protocol
class Combiner(Protocol):
def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ...
def batch_proc(data: Iterable[bytes], cb_results: Combiner) -> bytes:
for item in data:
...
def good_cb(*vals: bytes, maxlen: int | None = None) -> list[bytes]:
...
def bad_cb(*vals: bytes, maxitems: int | None) -> list[bytes]:
...
batch_proc([], good_cb) # OK
batch_proc([], bad_cb) # Error! Argument 2 has incompatible type because of
# different name and kind in the callback
接受其他可调用对象作为参数的可调用对象可以使用 ParamSpec
指示它们的参数类型相互依赖。此外,如果该可调用对象添加或删除其他可调用对象的参数,则可以使用 Concatenate
运算符。它们的形式分别为 Callable[ParamSpecVariable, ReturnType]
和 Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType]
。
3.10 版本中的更改: Callable
现在支持 ParamSpec
和 Concatenate
。有关更多详细信息,请参阅 PEP 612。
参见
ParamSpec
和 Concatenate
的文档提供了 Callable
中的用法示例。
泛型¶
由于无法以通用方式静态推断容器中对象的类型信息,标准库中的许多容器类都支持订阅来表示容器元素的预期类型。
from collections.abc import Mapping, Sequence
class Employee: ...
# Sequence[Employee] indicates that all elements in the sequence
# must be instances of "Employee".
# Mapping[str, str] indicates that all keys and all values in the mapping
# must be strings.
def notify_by_email(employees: Sequence[Employee],
overrides: Mapping[str, str]) -> None: ...
泛型函数和类可以使用类型参数语法进行参数化。
from collections.abc import Sequence
def first[T](l: Sequence[T]) -> T: # Function is generic over the TypeVar "T"
return l[0]
或者直接使用 TypeVar
工厂
from collections.abc import Sequence
from typing import TypeVar
U = TypeVar('U') # Declare type variable "U"
def second(l: Sequence[U]) -> U: # Function is generic over the TypeVar "U"
return l[1]
3.12 版本中的更改: 泛型的语法支持是 Python 3.12 中的新功能。
注解元组¶
对于 Python 中的大多数容器,类型系统假定容器中的所有元素都具有相同的类型。例如
from collections.abc import Mapping
# Type checker will infer that all elements in ``x`` are meant to be ints
x: list[int] = []
# Type checker error: ``list`` only accepts a single type argument:
y: list[int, str] = [1, 'foo']
# Type checker will infer that all keys in ``z`` are meant to be strings,
# and that all values in ``z`` are meant to be either strings or ints
z: Mapping[str, str | int] = {}
list
只接受一个类型参数,因此类型检查器将在上面的 y
赋值上发出错误。类似地,Mapping
只接受两个类型参数:第一个表示键的类型,第二个表示值的类型。
然而,与其他大多数 Python 容器不同,在地道的 Python 代码中,元组的元素不都是相同类型是很常见的。因此,元组在 Python 的类型系统中是特殊处理的。tuple
接受 任意数量 的类型参数
# OK: ``x`` is assigned to a tuple of length 1 where the sole element is an int
x: tuple[int] = (5,)
# OK: ``y`` is assigned to a tuple of length 2;
# element 1 is an int, element 2 is a str
y: tuple[int, str] = (5, "foo")
# Error: the type annotation indicates a tuple of length 1,
# but ``z`` has been assigned to a tuple of length 3
z: tuple[int] = (1, 2, 3)
要表示长度 任意 且所有元素都具有相同类型 T
的元组,请使用字面省略号 ...
:tuple[T, ...]
。要表示空元组,请使用 tuple[()]
。使用纯 tuple
作为注解等同于使用 tuple[Any, ...]
。
x: tuple[int, ...] = (1, 2)
# These reassignments are OK: ``tuple[int, ...]`` indicates x can be of any length
x = (1, 2, 3)
x = ()
# This reassignment is an error: all elements in ``x`` must be ints
x = ("foo", "bar")
# ``y`` can only ever be assigned to an empty tuple
y: tuple[()] = ()
z: tuple = ("foo", "bar")
# These reassignments are OK: plain ``tuple`` is equivalent to ``tuple[Any, ...]``
z = (1, 2, 3)
z = ()
类对象的类型¶
使用 C
注解的变量可以接受类型为 C
的值。相反,使用 type[C]
(或已弃用的 typing.Type[C]
)注解的变量可以接受本身就是类的值——具体来说,它将接受 C
的 类对象。例如
a = 3 # Has type ``int``
b = int # Has type ``type[int]``
c = type(a) # Also has type ``type[int]``
请注意,type[C]
是协变的
class User: ...
class ProUser(User): ...
class TeamUser(User): ...
def make_new_user(user_class: type[User]) -> User:
# ...
return user_class()
make_new_user(User) # OK
make_new_user(ProUser) # Also OK: ``type[ProUser]`` is a subtype of ``type[User]``
make_new_user(TeamUser) # Still fine
make_new_user(User()) # Error: expected ``type[User]`` but got ``User``
make_new_user(int) # Error: ``type[int]`` is not a subtype of ``type[User]``
type
的唯一合法参数是类、Any
、类型变量以及这些类型中的任意一种的联合。例如
def new_non_team_user(user_class: type[BasicUser | ProUser]): ...
new_non_team_user(BasicUser) # OK
new_non_team_user(ProUser) # OK
new_non_team_user(TeamUser) # Error: ``type[TeamUser]`` is not a subtype
# of ``type[BasicUser | ProUser]``
new_non_team_user(User) # Also an error
注解生成器和协程¶
生成器可以使用泛型类型 Generator[YieldType, SendType, ReturnType]
进行注解。例如
def echo_round() -> Generator[int, float, str]:
sent = yield 0
while sent >= 0:
sent = yield round(sent)
return 'Done'
请注意,与标准库中许多其他泛型类不同,Generator
的 SendType
行为是逆变而不是协变或不变。
SendType
和 ReturnType
参数默认为 None
def infinite_stream(start: int) -> Generator[int]:
while True:
yield start
start += 1
也可以明确设置这些类型
def infinite_stream(start: int) -> Generator[int, None, None]:
while True:
yield start
start += 1
仅生成值的简单生成器也可以注解为返回类型为 Iterable[YieldType]
或 Iterator[YieldType]
def infinite_stream(start: int) -> Iterator[int]:
while True:
yield start
start += 1
异步生成器以类似的方式处理,但不期望 ReturnType
类型参数(AsyncGenerator[YieldType, SendType]
)。SendType
参数默认为 None
,因此以下定义是等价的
async def infinite_stream(start: int) -> AsyncGenerator[int]:
while True:
yield start
start = await increment(start)
async def infinite_stream(start: int) -> AsyncGenerator[int, None]:
while True:
yield start
start = await increment(start)
与同步情况一样,AsyncIterable[YieldType]
和 AsyncIterator[YieldType]
也可用
async def infinite_stream(start: int) -> AsyncIterator[int]:
while True:
yield start
start = await increment(start)
协程可以使用 Coroutine[YieldType, SendType, ReturnType]
进行注解。泛型参数与 Generator
的参数相对应,例如
from collections.abc import Coroutine
c: Coroutine[list[str], str, int] # Some coroutine defined elsewhere
x = c.send('hi') # Inferred type of 'x' is list[str]
async def bar() -> None:
y = await c # Inferred type of 'y' is int
用户定义的泛型类型¶
用户定义的类可以定义为泛型类。
from logging import Logger
class LoggedVar[T]:
def __init__(self, value: T, name: str, logger: Logger) -> None:
self.name = name
self.logger = logger
self.value = value
def set(self, new: T) -> None:
self.log('Set ' + repr(self.value))
self.value = new
def get(self) -> T:
self.log('Get ' + repr(self.value))
return self.value
def log(self, message: str) -> None:
self.logger.info('%s: %s', self.name, message)
此语法表示类 LoggedVar
是围绕单个 类型变量 T
参数化的。这也使得 T
在类主体内作为类型有效。
泛型类隐式继承自 Generic
。为了与 Python 3.11 及更低版本兼容,也可以显式继承自 Generic
以指示泛型类。
from typing import TypeVar, Generic
T = TypeVar('T')
class LoggedVar(Generic[T]):
...
泛型类具有 __class_getitem__()
方法,这意味着它们可以在运行时进行参数化(例如下面的 LoggedVar[int]
)
from collections.abc import Iterable
def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
for var in vars:
var.set(0)
泛型类型可以有任意数量的类型变量。TypeVar
的所有变体都可以作为泛型类型的参数
from typing import TypeVar, Generic, Sequence
class WeirdTrio[T, B: Sequence[bytes], S: (int, str)]:
...
OldT = TypeVar('OldT', contravariant=True)
OldB = TypeVar('OldB', bound=Sequence[bytes], covariant=True)
OldS = TypeVar('OldS', int, str)
class OldWeirdTrio(Generic[OldT, OldB, OldS]):
...
传递给 Generic
的每个类型变量参数都必须是唯一的。因此,这是无效的
from typing import TypeVar, Generic
...
class Pair[M, M]: # SyntaxError
...
T = TypeVar('T')
class Pair(Generic[T, T]): # INVALID
...
泛型类也可以继承自其他类
from collections.abc import Sized
class LinkedList[T](Sized):
...
继承泛型类时,某些类型参数可以固定。
from collections.abc import Mapping
class MyDict[T](Mapping[str, T]):
...
在这种情况下,MyDict
有一个参数,T
。
使用不指定类型参数的泛型类将为每个位置假定 Any
。在以下示例中,MyIterable
不是泛型类,但隐式继承自 Iterable[Any]
。
from collections.abc import Iterable
class MyIterable(Iterable): # Same as Iterable[Any]
...
也支持用户定义的泛型类型别名。例如
from collections.abc import Iterable
type Response[S] = Iterable[S] | int
# Return type here is same as Iterable[str] | int
def response(query: str) -> Response[str]:
...
type Vec[T] = Iterable[tuple[T, T]]
def inproduct[T: (int, float, complex)](v: Vec[T]) -> T: # Same as Iterable[tuple[T, T]]
return sum(x*y for x, y in v)
为了向后兼容,泛型类型别名也可以通过简单赋值创建。
from collections.abc import Iterable
from typing import TypeVar
S = TypeVar("S")
Response = Iterable[S] | int
3.7 版本中的更改: Generic
不再具有自定义元类。
3.12 版本中的更改: 泛型和类型别名的语法支持是 3.12 版本中的新功能。以前,泛型类必须显式继承自 Generic
或在其某个基类中包含类型变量。
还通过参数规范变量以 [**P]
形式支持用于参数表达式的用户定义泛型。其行为与上面描述的类型变量一致,因为 typing
模块将参数规范变量视为特殊化的类型变量。唯一的例外是可以使用类型列表来替换 ParamSpec
。
>>> class Z[T, **P]: ... # T is a TypeVar; P is a ParamSpec
...
>>> Z[int, [dict, float]]
__main__.Z[int, [dict, float]]
泛型类 over ParamSpec
也可以通过显式继承自 Generic
创建。在这种情况下,不使用 **
。
from typing import ParamSpec, Generic
P = ParamSpec('P')
class Z(Generic[P]):
...
TypeVar
和 ParamSpec
之间的另一个区别是,只有一个参数规范变量的泛型将接受 X[[Type1, Type2, ...]]
形式的参数列表,以及出于美观原因的 X[Type1, Type2, ...]
形式。在内部,后者被转换为前者,因此以下两者是等价的
>>> class X[**P]: ...
...
>>> X[int, str]
__main__.X[[int, str]]
>>> X[[int, str]]
__main__.X[[int, str]]
请注意,带有 ParamSpec
的泛型在某些情况下在替换后可能没有正确的 __parameters__
,因为它们主要用于静态类型检查。
用户定义的泛型类可以具有 ABCs 作为基类,而不会发生元类冲突。不支持泛型元类。参数化泛型的结果被缓存,并且 typing
模块中的大多数类型都是可哈希的并且在相等性方面可比较。
Any
类型¶
一种特殊类型的类型是 Any
。静态类型检查器将把所有类型视为与 Any
兼容,并将 Any
视为与所有类型兼容。
这意味着可以对 Any
类型的值执行任何操作或方法调用,并将其赋值给任何变量。
from typing import Any
a: Any = None
a = [] # OK
a = 2 # OK
s: str = ''
s = a # OK
def foo(item: Any) -> int:
# Passes type checking; 'item' could be any type,
# and that type might have a 'bar' method
item.bar()
...
请注意,将 Any
类型的值分配给更精确的类型时,不会执行类型检查。例如,即使 s
被声明为 str
类型,并在运行时接收到一个 int
值,静态类型检查器在将 a
分配给 s
时也没有报告错误!
此外,所有没有返回类型或参数类型的函数将隐式默认使用 Any
。
def legacy_parser(text):
...
return data
# A static type checker will treat the above
# as having the same signature as:
def legacy_parser(text: Any) -> Any:
...
return data
这种行为允许 Any
作为 逃逸出口 使用,当您需要混合动态和静态类型代码时。
将 Any
的行为与 object
的行为进行对比。与 Any
类似,所有类型都是 object
的子类型。然而,与 Any
不同,反之则不然:object
不是 所有其他类型的子类型。
这意味着当一个值的类型是 object
时,类型检查器将拒绝对其进行几乎所有操作,将其分配给更专业类型的变量(或将其用作返回值)将是类型错误。例如
def hash_a(item: object) -> int:
# Fails type checking; an object does not have a 'magic' method.
item.magic()
...
def hash_b(item: Any) -> int:
# Passes type checking
item.magic()
...
# Passes type checking, since ints and strs are subclasses of object
hash_a(42)
hash_a("foo")
# Passes type checking, since Any is compatible with all types
hash_b(42)
hash_b("foo")
名义子类型与结构子类型¶
最初 PEP 484 将 Python 静态类型系统定义为使用 名义子类型。这意味着如果且仅当 A
是 B
的子类时,允许在预期类 B
的位置使用类 A
。
此要求以前也适用于抽象基类,例如 Iterable
。这种方法的缺点是类必须明确标记以支持它们,这不符合 Python 风格,也不像在习惯的动态类型 Python 代码中通常会做的那样。例如,这符合 PEP 484
from collections.abc import Sized, Iterable, Iterator
class Bucket(Sized, Iterable[int]):
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
PEP 544 允许通过允许用户在类定义中编写上述代码而无需显式基类来解决此问题,从而允许静态类型检查器将 Bucket
隐式视为 Sized
和 Iterable[int]
的子类型。这被称为 结构子类型(或静态鸭子类型)。
from collections.abc import Iterator, Iterable
class Bucket: # Note: no base classes
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
def collect(items: Iterable[int]) -> int: ...
result = collect(Bucket()) # Passes type check
此外,通过继承特殊的类 Protocol
,用户可以定义新的自定义协议以充分利用结构子类型(参见下面的示例)。
模块内容¶
typing
模块定义了以下类、函数和装饰器。
特殊类型提示原语¶
特殊类型¶
这些可用作注解中的类型。它们不支持使用 []
进行订阅。
- typing.AnyStr¶
一个 受限类型变量。
定义
AnyStr = TypeVar('AnyStr', str, bytes)
AnyStr
旨在用于可能接受str
或bytes
参数但不能允许两者混用的函数。例如:
def concat(a: AnyStr, b: AnyStr) -> AnyStr: return a + b concat("foo", "bar") # OK, output has type 'str' concat(b"foo", b"bar") # OK, output has type 'bytes' concat("foo", b"bar") # Error, cannot mix str and bytes
请注意,尽管其名称如此,
AnyStr
与Any
类型无关,也不表示“任何字符串”。特别是,AnyStr
和str | bytes
彼此不同,并且具有不同的用例# Invalid use of AnyStr: # The type variable is used only once in the function signature, # so cannot be "solved" by the type checker def greet_bad(cond: bool) -> AnyStr: return "hi there!" if cond else b"greetings!" # The better way of annotating this function: def greet_proper(cond: bool) -> str | bytes: return "hi there!" if cond else b"greetings!"
- typing.LiteralString¶
只包含字面字符串的特殊类型。
任何字符串字面量都与
LiteralString
兼容,另一个LiteralString
也是如此。但是,仅键入为str
的对象则不兼容。通过组合LiteralString
类型的对象创建的字符串也可用作LiteralString
。示例
def run_query(sql: LiteralString) -> None: ... def caller(arbitrary_string: str, literal_string: LiteralString) -> None: run_query("SELECT * FROM students") # OK run_query(literal_string) # OK run_query("SELECT * FROM " + literal_string) # OK run_query(arbitrary_string) # type checker error run_query( # type checker error f"SELECT * FROM students WHERE name = {arbitrary_string}" )
LiteralString
对于敏感的 API 很有用,其中任意用户生成的字符串可能会产生问题。例如,上面两个会生成类型检查器错误的案例可能会受到 SQL 注入攻击。有关更多详细信息,请参阅 PEP 675。
在 3.11 版本中新增。
- typing.Never¶
- typing.NoReturn¶
Never
和NoReturn
代表 底部类型,一个没有成员的类型。它们可用于指示函数永不返回,例如
sys.exit()
。from typing import Never # or NoReturn def stop() -> Never: raise RuntimeError('no way')
或者定义一个永远不应被调用的函数,因为没有有效的参数,例如
assert_never()
。from typing import Never # or NoReturn def never_call_me(arg: Never) -> None: pass def int_or_str(arg: int | str) -> None: never_call_me(arg) # type checker error match arg: case int(): print("It's an int") case str(): print("It's a str") case _: never_call_me(arg) # OK, arg is of type Never (or NoReturn)
Never
和NoReturn
在类型系统中具有相同的含义,静态类型检查器将两者同等对待。3.6.2 版本新增: 增加了
NoReturn
。3.11 版本新增: 增加了
Never
。
- typing.Self¶
表示当前封闭类的特殊类型。
例如:
from typing import Self, reveal_type class Foo: def return_self(self) -> Self: ... return self class SubclassOfFoo(Foo): pass reveal_type(Foo().return_self()) # Revealed type is "Foo" reveal_type(SubclassOfFoo().return_self()) # Revealed type is "SubclassOfFoo"
此注解在语义上等同于以下内容,尽管方式更简洁
from typing import TypeVar Self = TypeVar("Self", bound="Foo") class Foo: def return_self(self: Self) -> Self: ... return self
通常,如果某个方法返回
self
,如上述示例所示,您应该使用Self
作为返回注解。如果Foo.return_self
被注解为返回"Foo"
,那么类型检查器将推断SubclassOfFoo.return_self
返回的对象类型为Foo
而不是SubclassOfFoo
。其他常见用例包括
用作替代构造函数并返回
cls
参数实例的classmethod
。注解返回自身的
__enter__()
方法。
如果方法不保证在子类化时返回子类的实例,则不应使用
Self
作为返回注解。class Eggs: # Self would be an incorrect return annotation here, # as the object returned is always an instance of Eggs, # even in subclasses def returns_eggs(self) -> "Eggs": return Eggs()
有关更多详细信息,请参阅 PEP 673。
在 3.11 版本中新增。
- typing.TypeAlias¶
明确声明类型别名的特殊注解。
例如:
from typing import TypeAlias Factors: TypeAlias = list[int]
TypeAlias
在较旧的 Python 版本上特别有用,用于注解使用前向引用的别名,因为类型检查器很难将这些与普通变量赋值区分开来。from typing import Generic, TypeAlias, TypeVar T = TypeVar("T") # "Box" does not exist yet, # so we have to use quotes for the forward reference on Python <3.12. # Using ``TypeAlias`` tells the type checker that this is a type alias declaration, # not a variable assignment to a string. BoxOfStrings: TypeAlias = "Box[str]" class Box(Generic[T]): @classmethod def make_box_of_strings(cls) -> BoxOfStrings: ...
有关更多详细信息,请参阅 PEP 613。
在 3.10 版本加入。
自 3.12 版弃用:
TypeAlias
已弃用,取而代之的是type
语句,该语句创建TypeAliasType
的实例,并原生支持前向引用。请注意,虽然TypeAlias
和TypeAliasType
具有相似的用途和名称,但它们是不同的,后者不是前者的类型。目前没有计划移除TypeAlias
,但建议用户迁移到type
语句。
特殊形式¶
这些可用作注解中的类型。它们都支持使用 []
进行订阅,但每个都具有独特的语法。
- class typing.Union¶
联合类型;
Union[X, Y]
等同于X | Y
,表示 X 或 Y。要定义联合,请使用例如
Union[int, str]
或简写int | str
。建议使用简写。详细信息参数必须是类型,并且必须至少有一个。
联合的联合会被展平,例如
Union[Union[int, str], float] == Union[int, str, float]
但是,这不适用于通过类型别名引用的联合,以避免强制评估底层
TypeAliasType
。type A = Union[int, str] Union[A, float] != Union[int, str, float]
单个参数的联合会消失,例如
Union[int] == int # The constructor actually returns int
冗余参数会被跳过,例如
Union[int, str, int] == Union[int, str] == int | str
比较联合时,参数顺序将被忽略,例如
Union[int, str] == Union[str, int]
您不能子类化或实例化
Union
。您不能写入
Union[X][Y]
。
3.7 版本中的更改: 在运行时不从联合中移除显式子类。
3.10 版本中的更改: 联合现在可以写为
X | Y
。请参阅联合类型表达式。3.14 版本中的更改:
types.UnionType
现在是Union
的别名,并且Union[int, str]
和int | str
都创建同一类的实例。要在运行时检查对象是否为Union
,请使用isinstance(obj, Union)
。为了与 Python 的早期版本兼容,请使用get_origin(obj) is typing.Union or get_origin(obj) is types.UnionType
。
- typing.Optional¶
Optional[X]
等同于X | None
(或Union[X, None]
)。请注意,这与可选参数的概念不同,可选参数是具有默认值的参数。具有默认值的可选参数不需要其类型注解上的
Optional
限定符,仅仅因为它可选。例如def foo(arg: int = 0) -> None: ...
另一方面,如果允许
None
的显式值,则使用Optional
是合适的,无论参数是否可选。例如def foo(arg: Optional[int] = None) -> None: ...
3.10 版本中的更改: Optional 现在可以写为
X | None
。请参阅联合类型表达式。
- typing.Concatenate¶
用于注解高阶函数的特殊形式。
Concatenate
可以与 Callable 和ParamSpec
结合使用,以注解一个添加、移除或转换另一个可调用对象参数的高阶可调用对象。用法形式为Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]
。Concatenate
目前仅在用作 Callable 的第一个参数时有效。Concatenate
的最后一个参数必须是ParamSpec
或省略号(...
)。例如,要注解一个装饰器
with_lock
,它为被装饰函数提供一个threading.Lock
,可以使用Concatenate
来指示with_lock
期望一个可调用对象,该对象以Lock
作为第一个参数,并返回一个具有不同类型签名的可调用对象。在这种情况下,ParamSpec
表示返回的可调用对象的参数类型取决于传入的可调用对象的参数类型。from collections.abc import Callable from threading import Lock from typing import Concatenate # Use this lock to ensure that only one thread is executing a function # at any time. my_lock = Lock() def with_lock[**P, R](f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]: '''A type-safe decorator which provides a lock.''' def inner(*args: P.args, **kwargs: P.kwargs) -> R: # Provide the lock as the first argument. return f(my_lock, *args, **kwargs) return inner @with_lock def sum_threadsafe(lock: Lock, numbers: list[float]) -> float: '''Add a list of numbers together in a thread-safe manner.''' with lock: return sum(numbers) # We don't need to pass in the lock ourselves thanks to the decorator. sum_threadsafe([1.1, 2.2, 3.3])
在 3.10 版本加入。
- typing.Literal¶
用于定义“字面量类型”的特殊类型形式。
Literal
可用于向类型检查器指示注解对象的值等同于提供的字面量之一。例如:
def validate_simple(data: Any) -> Literal[True]: # always returns True ... type Mode = Literal['r', 'rb', 'w', 'wb'] def open_helper(file: str, mode: Mode) -> str: ... open_helper('/some/path', 'r') # Passes type check open_helper('/other/path', 'typo') # Error in type checker
Literal[...]
不能被子类化。在运行时,任意值都可以作为Literal[...]
的类型参数,但类型检查器可能会施加限制。有关字面量类型的更多详细信息,请参阅 PEP 586。附加详情
参数必须是字面量值,并且必须至少有一个。
嵌套的
Literal
类型会被展平,例如assert Literal[Literal[1, 2], 3] == Literal[1, 2, 3]
但是,这不适用于通过类型别名引用的
Literal
类型,以避免强制评估底层TypeAliasType
。type A = Literal[1, 2] assert Literal[A, 3] != Literal[1, 2, 3]
冗余参数会被跳过,例如
assert Literal[1, 2, 1] == Literal[1, 2]
比较字面量时,参数顺序将被忽略,例如
assert Literal[1, 2] == Literal[2, 1]
您不能子类化或实例化
Literal
。您不能写入
Literal[X][Y]
。
在 3.8 版本加入。
- typing.ClassVar¶
用于标记类变量的特殊类型构造。
如 PEP 526 中所介绍,用 ClassVar 包装的变量注解表示给定属性旨在用作类变量,并且不应在类的实例上设置。用法
class Starship: stats: ClassVar[dict[str, int]] = {} # class variable damage: int = 10 # instance variable
ClassVar
只接受类型,不能进一步订阅。ClassVar
本身不是一个类,不应与isinstance()
或issubclass()
一起使用。ClassVar
不会改变 Python 运行时行为,但可以被第三方类型检查器使用。例如,类型检查器可能会将以下代码标记为错误enterprise_d = Starship(3000) enterprise_d.stats = {} # Error, setting class variable on instance Starship.stats = {} # This is OK
3.5.3 版本新增。
- typing.Final¶
用于向类型检查器指示最终名称的特殊类型构造。
最终名称不能在任何作用域中重新赋值。在类作用域中声明的最终名称不能在子类中被覆盖。
例如:
MAX_SIZE: Final = 9000 MAX_SIZE += 1 # Error reported by type checker class Connection: TIMEOUT: Final[int] = 10 class FastConnector(Connection): TIMEOUT = 1 # Error reported by type checker
这些属性没有运行时检查。有关更多详细信息,请参阅 PEP 591。
在 3.8 版本加入。
- typing.Required¶
用于将
TypedDict
键标记为必需的特殊类型构造。这主要用于
total=False
的 TypedDicts。有关更多详细信息,请参阅TypedDict
和 PEP 655。在 3.11 版本中新增。
- typing.ReadOnly¶
一个特殊的类型构造,用于将
TypedDict
的项标记为只读。例如:
class Movie(TypedDict): title: ReadOnly[str] year: int def mutate_movie(m: Movie) -> None: m["year"] = 1999 # allowed m["title"] = "The Matrix" # typechecker error
此属性没有运行时检查。
有关更多详细信息,请参阅
TypedDict
和 PEP 705。在 3.13 版本加入。
- typing.Annotated¶
用于向注解添加上下文特定元数据的特殊类型形式。
通过使用注解
Annotated[T, x]
将元数据x
添加到给定类型T
。使用Annotated
添加的元数据可用于静态分析工具或在运行时。在运行时,元数据存储在__metadata__
属性中。如果库或工具遇到注解
Annotated[T, x]
并且对元数据没有特殊逻辑,它应该忽略元数据并简单地将注解视为T
。因此,当代码希望将注解用于 Python 静态类型系统之外的目的时,Annotated
会很有用。使用
Annotated[T, x]
作为注解仍然允许对T
进行静态类型检查,因为类型检查器将简单地忽略元数据x
。通过这种方式,Annotated
与@no_type_check
装饰器不同,后者也可以用于在类型系统范围之外添加注解,但会完全禁用函数或类的类型检查。如何解释元数据的责任在于遇到
Annotated
注解的工具或库。遇到Annotated
类型的工具或库可以扫描元数据元素以确定它们是否感兴趣(例如,使用isinstance()
)。- Annotated[<type>, <metadata>]
这是一个示例,说明如何在进行范围分析时使用
Annotated
向类型注解添加元数据。@dataclass class ValueRange: lo: int hi: int T1 = Annotated[int, ValueRange(-10, 5)] T2 = Annotated[T1, ValueRange(-20, 3)]
Annotated
的第一个参数必须是有效类型。可以提供多个元数据元素,因为Annotated
支持可变参数。元数据元素的顺序会保留并影响相等性检查。@dataclass class ctype: kind: str a1 = Annotated[int, ValueRange(3, 10), ctype("char")] a2 = Annotated[int, ctype("char"), ValueRange(3, 10)] assert a1 != a2 # Order matters
由使用注解的工具决定是否允许客户端向一个注解添加多个元数据元素以及如何合并这些注解。
嵌套的
Annotated
类型会被展平。元数据元素的顺序从最内层注解开始assert Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[ int, ValueRange(3, 10), ctype("char") ]
但是,这不适用于通过类型别名引用的
Annotated
类型,以避免强制评估底层TypeAliasType
。type From3To10[T] = Annotated[T, ValueRange(3, 10)] assert Annotated[From3To10[int], ctype("char")] != Annotated[ int, ValueRange(3, 10), ctype("char") ]
重复的元数据元素不会被移除。
assert Annotated[int, ValueRange(3, 10)] != Annotated[ int, ValueRange(3, 10), ValueRange(3, 10) ]
Annotated
可用于嵌套和泛型别名@dataclass class MaxLen: value: int type Vec[T] = Annotated[list[tuple[T, T]], MaxLen(10)] # When used in a type annotation, a type checker will treat "V" the same as # ``Annotated[list[tuple[int, int]], MaxLen(10)]``: type V = Vec[int]
Annotated
不能与解包的TypeVarTuple
一起使用type Variadic[*Ts] = Annotated[*Ts, Ann1] = Annotated[T1, T2, T3, ..., Ann1] # NOT valid
其中
T1
、T2
等是TypeVars
。这是无效的,因为只能向 Annotated 传递一个类型。默认情况下,
get_type_hints()
会从注解中去除元数据。传入include_extras=True
以保留元数据。>>> from typing import Annotated, get_type_hints >>> def func(x: Annotated[int, "metadata"]) -> None: pass ... >>> get_type_hints(func) {'x': <class 'int'>, 'return': <class 'NoneType'>} >>> get_type_hints(func, include_extras=True) {'x': typing.Annotated[int, 'metadata'], 'return': <class 'NoneType'>}
在运行时,与
Annotated
类型关联的元数据可以通过__metadata__
属性检索>>> from typing import Annotated >>> X = Annotated[int, "very", "important", "metadata"] >>> X typing.Annotated[int, 'very', 'important', 'metadata'] >>> X.__metadata__ ('very', 'important', 'metadata')
如果要检索由
Annotated
包装的原始类型,请使用__origin__
属性>>> from typing import Annotated, get_origin >>> Password = Annotated[str, "secret"] >>> Password.__origin__ <class 'str'>
请注意,使用
get_origin()
将返回Annotated
本身。>>> get_origin(Password) typing.Annotated
参见
- PEP 593 - 灵活的函数和变量注解
PEP 将
Annotated
引入标准库。
在 3.9 版本中新增。
- typing.TypeIs¶
用于标记用户定义的类型谓词函数的特殊类型构造。
TypeIs
可用于注解用户定义的类型谓词函数的返回类型。TypeIs
只接受一个类型参数。在运行时,以这种方式标记的函数应返回布尔值并至少接受一个位置参数。TypeIs
旨在有利于 类型窄化 —— 静态类型检查器用来确定程序代码流中表达式更精确类型的一种技术。通常,类型窄化是通过分析条件代码流并将窄化应用于代码块来完成的。这里的条件表达式有时被称为“类型谓词”。def is_str(val: str | float): # "isinstance" type predicate if isinstance(val, str): # Type of ``val`` is narrowed to ``str`` ... else: # Else, type of ``val`` is narrowed to ``float``. ...
有时使用用户定义的布尔函数作为类型谓词会很方便。这样的函数应该使用
TypeIs[...]
或TypeGuard
作为其返回类型,以提醒静态类型检查器此意图。TypeIs
通常比TypeGuard
具有更直观的行为,但当输入和输出类型不兼容(例如,list[object]
到list[int]
)或当函数不为窄化类型的所有实例返回True
时,它不能使用。使用
-> TypeIs[NarrowedType]
可以告诉静态类型检查器,对于给定函数其返回值是一个布尔值。
如果返回值为
True
,则其参数的类型是参数原始类型和NarrowedType
的交集。如果返回值为
False
,则其参数的类型将被缩小以排除NarrowedType
。
例如:
from typing import assert_type, final, TypeIs class Parent: pass class Child(Parent): pass @final class Unrelated: pass def is_parent(val: object) -> TypeIs[Parent]: return isinstance(val, Parent) def run(arg: Child | Unrelated): if is_parent(arg): # Type of ``arg`` is narrowed to the intersection # of ``Parent`` and ``Child``, which is equivalent to # ``Child``. assert_type(arg, Child) else: # Type of ``arg`` is narrowed to exclude ``Parent``, # so only ``Unrelated`` is left. assert_type(arg, Unrelated)
TypeIs
中的类型必须与函数参数的类型一致;否则,静态类型检查器将引发错误。错误编写的TypeIs
函数可能导致类型系统中的不健全行为;用户有责任以类型安全的方式编写此类函数。如果
TypeIs
函数是类或实例方法,则TypeIs
中的类型映射到第二个参数的类型(在cls
或self
之后)。简而言之,形式为
def foo(arg: TypeA) -> TypeIs[TypeB]: ...
,意味着如果foo(arg)
返回True
,则arg
是TypeB
的一个实例;如果返回False
,则不是TypeB
的实例。TypeIs
也适用于类型变量。有关更多信息,请参阅 PEP 742(使用TypeIs
缩小类型)。在 3.13 版本加入。
- typing.TypeGuard¶
用于标记用户定义的类型谓词函数的特殊类型构造。
类型谓词函数是用户定义的函数,用于返回其参数是否是特定类型的实例。
TypeGuard
的工作方式与TypeIs
类似,但对类型检查行为有微妙的差异(见下文)。使用
-> TypeGuard
告诉静态类型检查器,对于给定函数其返回值是一个布尔值。
如果返回值为
True
,则其参数的类型是TypeGuard
中的类型。
TypeGuard
也适用于类型变量。有关更多详细信息,请参阅 PEP 647。例如:
def is_str_list(val: list[object]) -> TypeGuard[list[str]]: '''Determines whether all objects in the list are strings''' return all(isinstance(x, str) for x in val) def func1(val: list[object]): if is_str_list(val): # Type of ``val`` is narrowed to ``list[str]``. print(" ".join(val)) else: # Type of ``val`` remains as ``list[object]``. print("Not a list of strings!")
TypeIs
和TypeGuard
的区别如下TypeIs
要求缩小后的类型是输入类型的子类型,而TypeGuard
则不要求。主要原因是允许将list[object]
缩小为list[str]
之类的情况,尽管后者不是前者的子类型,因为list
是不变的。当
TypeGuard
函数返回True
时,类型检查器将变量的类型精确地缩小为TypeGuard
类型。当TypeIs
函数返回True
时,类型检查器可以推断出更精确的类型,将变量先前已知的类型与TypeIs
类型结合起来。(从技术上讲,这被称为交集类型。)当
TypeGuard
函数返回False
时,类型检查器根本无法缩小变量的类型。当TypeIs
函数返回False
时,类型检查器可以将变量的类型缩小以排除TypeIs
类型。
在 3.10 版本加入。
- typing.Unpack¶
类型操作符,用于概念上标记一个对象已被解包。
例如,在 类型变量元组 上使用解包操作符
*
等同于使用Unpack
将类型变量元组标记为已解包Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Effectively does: tup: tuple[Unpack[Ts]]
实际上,在
typing.TypeVarTuple
和builtins.tuple
类型的上下文中,Unpack
可以与*
互换使用。在较旧的 Python 版本中,你可能会看到Unpack
被显式使用,因为*
无法在某些地方使用# In older versions of Python, TypeVarTuple and Unpack # are located in the `typing_extensions` backports package. from typing_extensions import TypeVarTuple, Unpack Ts = TypeVarTuple('Ts') tup: tuple[*Ts] # Syntax error on Python <= 3.10! tup: tuple[Unpack[Ts]] # Semantically equivalent, and backwards-compatible
Unpack
还可以与typing.TypedDict
一起用于在函数签名中为**kwargs
键入类型from typing import TypedDict, Unpack class Movie(TypedDict): name: str year: int # This function expects two keyword arguments - `name` of type `str` # and `year` of type `int`. def foo(**kwargs: Unpack[Movie]): ...
有关使用
Unpack
进行**kwargs
类型键入的更多详细信息,请参阅 PEP 692。在 3.11 版本中新增。
构建泛型类型和类型别名¶
以下类不应直接用作注解。它们旨在作为创建泛型类型和类型别名的构建块。
这些对象可以通过特殊语法(类型参数列表 和 type
语句)创建。为了与 Python 3.11 及更早版本兼容,它们也可以不使用专用语法创建,如下所述。
- class typing.Generic¶
泛型类型的抽象基类。
泛型类型通常通过在类名后添加类型参数列表来声明
class Mapping[KT, VT]: def __getitem__(self, key: KT) -> VT: ... # Etc.
这样的类隐式地继承自
Generic
。此语法的运行时语义在 语言参考 中讨论。然后可以如下使用此类
def lookup_name[X, Y](mapping: Mapping[X, Y], key: X, default: Y) -> Y: try: return mapping[key] except KeyError: return default
此处函数名后面的括号表示一个 泛型函数。
为了向后兼容,泛型类也可以通过显式继承自
Generic
来声明。在这种情况下,类型参数必须单独声明KT = TypeVar('KT') VT = TypeVar('VT') class Mapping(Generic[KT, VT]): def __getitem__(self, key: KT) -> VT: ... # Etc.
- class typing.TypeVar(name, *constraints, bound=None, covariant=False, contravariant=False, infer_variance=False, default=typing.NoDefault)¶
类型变量。
构造类型变量的首选方式是通过 泛型函数、泛型类 和 泛型类型别名 的专用语法
class Sequence[T]: # T is a TypeVar ...
此语法还可用于创建有界和受约束的类型变量
class StrSequence[S: str]: # S is a TypeVar with a `str` upper bound; ... # we can say that S is "bounded by `str`" class StrOrBytesSequence[A: (str, bytes)]: # A is a TypeVar constrained to str or bytes ...
但是,如果需要,可重用类型变量也可以手动构造,如下所示
T = TypeVar('T') # Can be anything S = TypeVar('S', bound=str) # Can be any subtype of str A = TypeVar('A', str, bytes) # Must be exactly str or bytes
类型变量主要用于静态类型检查器。它们作为泛型类型以及泛型函数和类型别名定义的参数。有关泛型类型的更多信息,请参阅
Generic
。泛型函数的工作原理如下def repeat[T](x: T, n: int) -> Sequence[T]: """Return a list containing n references to x.""" return [x]*n def print_capitalized[S: str](x: S) -> S: """Print x capitalized, and return x.""" print(x.capitalize()) return x def concatenate[A: (str, bytes)](x: A, y: A) -> A: """Add two strings or bytes objects together.""" return x + y
请注意,类型变量可以是 *有界的*、*受约束的*,或两者都不是,但不能同时是有界的 *和* 受约束的。
类型变量的方差由类型检查器在通过 类型参数语法 创建时,或传入
infer_variance=True
时推断。手动创建的类型变量可以通过传入covariant=True
或contravariant=True
显式标记为协变或逆变。默认情况下,手动创建的类型变量是不变的。有关更多详细信息,请参阅 PEP 484 和 PEP 695。有界类型变量和受约束类型变量在几个重要方面具有不同的语义。使用 *有界* 类型变量意味着
TypeVar
将使用最具体的类型求解x = print_capitalized('a string') reveal_type(x) # revealed type is str class StringSubclass(str): pass y = print_capitalized(StringSubclass('another string')) reveal_type(y) # revealed type is StringSubclass z = print_capitalized(45) # error: int is not a subtype of str
类型变量的上限可以是具体类型、抽象类型(ABC 或 Protocol),甚至是类型联合
# Can be anything with an __abs__ method def print_abs[T: SupportsAbs](arg: T) -> None: print("Absolute value:", abs(arg)) U = TypeVar('U', bound=str|bytes) # Can be any subtype of the union str|bytes V = TypeVar('V', bound=SupportsAbs) # Can be anything with an __abs__ method
然而,使用 *受约束* 类型变量意味着
TypeVar
只能被求解为正好是给定约束之一a = concatenate('one', 'two') reveal_type(a) # revealed type is str b = concatenate(StringSubclass('one'), StringSubclass('two')) reveal_type(b) # revealed type is str, despite StringSubclass being passed in c = concatenate('one', b'two') # error: type variable 'A' can be either str or bytes in a function call, but not both
在运行时,
isinstance(x, T)
将引发TypeError
。- __name__¶
类型变量的名称。
- __covariant__¶
类型变量是否已显式标记为协变。
- __contravariant__¶
类型变量是否已显式标记为逆变。
- __infer_variance__¶
类型检查器是否应推断类型变量的方差。
3.12 新版功能.
- __bound__¶
类型变量的上限(如果有)。
- evaluate_bound()¶
一个 评估函数,对应于
__bound__
属性。直接调用时,此方法仅支持VALUE
格式,这等同于直接访问__bound__
属性,但方法对象可以传递给annotationlib.call_evaluate_function()
以不同格式评估值。在 3.14 版本加入。
- __constraints__¶
包含类型变量约束的元组(如果有)。
- evaluate_constraints()¶
一个 评估函数,对应于
__constraints__
属性。直接调用时,此方法仅支持VALUE
格式,这等同于直接访问__constraints__
属性,但方法对象可以传递给annotationlib.call_evaluate_function()
以不同格式评估值。在 3.14 版本加入。
- __default__¶
类型变量的默认值,如果没有默认值,则为
typing.NoDefault
。在 3.13 版本加入。
- evaluate_default()¶
一个 评估函数,对应于
__default__
属性。直接调用时,此方法仅支持VALUE
格式,这等同于直接访问__default__
属性,但方法对象可以传递给annotationlib.call_evaluate_function()
以不同格式评估值。在 3.14 版本加入。
- has_default()¶
返回类型变量是否具有默认值。这等同于检查
__default__
是否不是typing.NoDefault
单例,只是它不会强制评估 惰性评估 的默认值。在 3.13 版本加入。
3.13 版本中的变化: 添加了对默认值的支持。
- class typing.TypeVarTuple(name, *, default=typing.NoDefault)¶
类型变量元组。类型变量 的一种特殊形式,支持 *可变参数* 泛型。
类型变量元组可以在 类型参数列表 中使用名称前的一个星号 (
*
) 声明def move_first_element_to_last[T, *Ts](tup: tuple[T, *Ts]) -> tuple[*Ts, T]: return (*tup[1:], tup[0])
或者通过显式调用
TypeVarTuple
构造函数T = TypeVar("T") Ts = TypeVarTuple("Ts") def move_first_element_to_last(tup: tuple[T, *Ts]) -> tuple[*Ts, T]: return (*tup[1:], tup[0])
普通类型变量允许使用单一类型进行参数化。相比之下,类型变量元组通过像元组中包含任意数量的类型变量一样,允许使用 *任意* 数量的类型进行参数化。例如
# T is bound to int, Ts is bound to () # Return value is (1,), which has type tuple[int] move_first_element_to_last(tup=(1,)) # T is bound to int, Ts is bound to (str,) # Return value is ('spam', 1), which has type tuple[str, int] move_first_element_to_last(tup=(1, 'spam')) # T is bound to int, Ts is bound to (str, float) # Return value is ('spam', 3.0, 1), which has type tuple[str, float, int] move_first_element_to_last(tup=(1, 'spam', 3.0)) # This fails to type check (and fails at runtime) # because tuple[()] is not compatible with tuple[T, *Ts] # (at least one element is required) move_first_element_to_last(tup=())
注意
tuple[T, *Ts]
中解包操作符*
的使用。概念上,你可以将Ts
视为一个类型变量元组(T1, T2, ...)
。tuple[T, *Ts]
将变为tuple[T, *(T1, T2, ...)]
,这等同于tuple[T, T1, T2, ...]
。(请注意,在较旧的 Python 版本中,你可能会看到使用Unpack
来编写,例如Unpack[Ts]
。)类型变量元组必须 *始终* 被解包。这有助于将类型变量元组与普通类型变量区分开来
x: Ts # Not valid x: tuple[Ts] # Not valid x: tuple[*Ts] # The correct way to do it
类型变量元组可以在与普通类型变量相同的上下文中使用。例如,在类定义、参数和返回类型中
class Array[*Shape]: def __getitem__(self, key: tuple[*Shape]) -> float: ... def __abs__(self) -> "Array[*Shape]": ... def get_shape(self) -> tuple[*Shape]: ...
类型变量元组可以与普通类型变量很好地结合使用
class Array[DType, *Shape]: # This is fine pass class Array2[*Shape, DType]: # This would also be fine pass class Height: ... class Width: ... float_array_1d: Array[float, Height] = Array() # Totally fine int_array_2d: Array[int, Height, Width] = Array() # Yup, fine too
但是,请注意,在单个类型参数列表或类型参数列表中最多只能出现一个类型变量元组
x: tuple[*Ts, *Ts] # Not valid class Array[*Shape, *Shape]: # Not valid pass
最后,解包的类型变量元组可以用作
*args
的类型注解def call_soon[*Ts]( callback: Callable[[*Ts], None], *args: *Ts ) -> None: ... callback(*args)
与
*args
的未解包注解(例如*args: int
,这将指定 *所有* 参数都是int
)相反,*args: *Ts
允许引用*args
中 *单个* 参数的类型。在这里,这允许我们确保传递给call_soon
的*args
的类型与callback
的(位置)参数的类型匹配。有关类型变量元组的更多详细信息,请参阅 PEP 646。
- __name__¶
类型变量元组的名称。
- __default__¶
类型变量元组的默认值,如果没有默认值,则为
typing.NoDefault
。在 3.13 版本加入。
- evaluate_default()¶
一个 评估函数,对应于
__default__
属性。直接调用时,此方法仅支持VALUE
格式,这等同于直接访问__default__
属性,但方法对象可以传递给annotationlib.call_evaluate_function()
以不同格式评估值。在 3.14 版本加入。
- has_default()¶
返回类型变量元组是否具有默认值。这等同于检查
__default__
是否不是typing.NoDefault
单例,只是它不会强制评估 惰性评估 的默认值。在 3.13 版本加入。
在 3.11 版本中新增。
3.13 版本中的变化: 添加了对默认值的支持。
- class typing.ParamSpec(name, *, bound=None, covariant=False, contravariant=False, default=typing.NoDefault)¶
参数规范变量。类型变量 的一种特殊版本。
在 类型参数列表 中,参数规范可以用两个星号 (
**
) 声明type IntFunc[**P] = Callable[P, int]
为了与 Python 3.11 及更早版本兼容,
ParamSpec
对象也可以按如下方式创建P = ParamSpec('P')
参数规范变量主要用于静态类型检查器。它们用于将一个可调用对象的参数类型转发到另一个可调用对象——这种模式常见于高阶函数和装饰器中。它们仅在
Concatenate
中,或作为Callable
的第一个参数,或作为用户定义泛型的参数时有效。有关泛型类型的更多信息,请参阅Generic
。例如,要为函数添加基本日志记录,可以创建一个装饰器
add_logging
来记录函数调用。参数规范变量告诉类型检查器,传入装饰器的可调用对象和它返回的新可调用对象具有相互依赖的类型参数from collections.abc import Callable import logging def add_logging[T, **P](f: Callable[P, T]) -> Callable[P, T]: '''A type-safe decorator to add logging to a function.''' def inner(*args: P.args, **kwargs: P.kwargs) -> T: logging.info(f'{f.__name__} was called') return f(*args, **kwargs) return inner @add_logging def add_two(x: float, y: float) -> float: '''Add two numbers together.''' return x + y
如果没有
ParamSpec
,之前标注此函数的最简单方法是使用一个上限为Callable[..., Any]
的TypeVar
。但这会导致两个问题类型检查器无法类型检查
inner
函数,因为*args
和**kwargs
必须被类型化为Any
。在返回
inner
函数时,可能需要在add_logging
装饰器的主体中使用cast()
,或者必须告知静态类型检查器忽略return inner
。
- args¶
- kwargs¶
由于
ParamSpec
捕获位置参数和关键字参数,因此可以使用P.args
和P.kwargs
将ParamSpec
拆分为其组件。P.args
表示给定调用中的位置参数元组,并且应仅用于注解*args
。P.kwargs
表示给定调用中关键字参数到其值的映射,并且应仅用于注解**kwargs
。这两个属性都要求注解的参数在作用域内。在运行时,P.args
和P.kwargs
分别是ParamSpecArgs
和ParamSpecKwargs
的实例。
- __name__¶
参数规范的名称。
- __default__¶
参数规范的默认值,如果没有默认值,则为
typing.NoDefault
。在 3.13 版本加入。
- evaluate_default()¶
一个 评估函数,对应于
__default__
属性。直接调用时,此方法仅支持VALUE
格式,这等同于直接访问__default__
属性,但方法对象可以传递给annotationlib.call_evaluate_function()
以不同格式评估值。在 3.14 版本加入。
- has_default()¶
返回参数规范是否具有默认值。这等同于检查
__default__
是否不是typing.NoDefault
单例,只是它不会强制评估 惰性评估 的默认值。在 3.13 版本加入。
使用
covariant=True
或contravariant=True
创建的参数规范变量可用于声明协变或逆变泛型类型。bound
参数也接受,类似于TypeVar
。但是,这些关键字的实际语义尚待确定。在 3.10 版本加入。
3.13 版本中的变化: 添加了对默认值的支持。
备注
只有在全局作用域中定义的参数规范变量才能被 pickle。
参见
PEP 612 – 参数规范变量(引入
ParamSpec
和Concatenate
的 PEP)
- typing.ParamSpecArgs¶
- typing.ParamSpecKwargs¶
ParamSpec
的参数和关键字参数属性。ParamSpec
的P.args
属性是ParamSpecArgs
的实例,而P.kwargs
是ParamSpecKwargs
的实例。它们旨在用于运行时内省,对静态类型检查器没有特殊含义。对这些对象中的任何一个调用
get_origin()
将返回原始的ParamSpec
>>> from typing import ParamSpec, get_origin >>> P = ParamSpec("P") >>> get_origin(P.args) is P True >>> get_origin(P.kwargs) is P True
在 3.10 版本加入。
- class typing.TypeAliasType(name, value, *, type_params=())¶
通过
type
语句创建的类型别名的类型。示例
>>> type Alias = int >>> type(Alias) <class 'typing.TypeAliasType'>
3.12 新版功能.
- __name__¶
类型别名的名称
>>> type Alias = int >>> Alias.__name__ 'Alias'
- __module__¶
定义类型别名的模块名称
>>> type Alias = int >>> Alias.__module__ '__main__'
- __type_params__¶
类型别名的类型参数,如果别名不是泛型的,则为空元组
>>> type ListOrSet[T] = list[T] | set[T] >>> ListOrSet.__type_params__ (T,) >>> type NotGeneric = int >>> NotGeneric.__type_params__ ()
- __value__¶
类型别名的值。这是 惰性评估 的,因此别名定义中使用的名称直到访问
__value__
属性时才会被解析>>> type Mutually = Recursive >>> type Recursive = Mutually >>> Mutually Mutually >>> Recursive Recursive >>> Mutually.__value__ Recursive >>> Recursive.__value__ Mutually
- evaluate_value()¶
一个 评估函数,对应于
__value__
属性。直接调用时,此方法仅支持VALUE
格式,这等同于直接访问__value__
属性,但方法对象可以传递给annotationlib.call_evaluate_function()
以不同格式评估值>>> type Alias = undefined >>> Alias.__value__ Traceback (most recent call last): ... NameError: name 'undefined' is not defined >>> from annotationlib import Format, call_evaluate_function >>> Alias.evaluate_value(Format.VALUE) Traceback (most recent call last): ... NameError: name 'undefined' is not defined >>> call_evaluate_function(Alias.evaluate_value, Format.FORWARDREF) ForwardRef('undefined')
在 3.14 版本加入。
解包
类型别名支持使用
*Alias
语法进行星号解包。这等同于直接使用Unpack[Alias]
>>> type Alias = tuple[int, str] >>> type Unpacked = tuple[bool, *Alias] >>> Unpacked.__value__ tuple[bool, typing.Unpack[Alias]]
在 3.14 版本加入。
其他特殊指令¶
这些函数和类不应直接用作注解。它们旨在作为创建和声明类型的构建块。
- class typing.NamedTuple¶
collections.namedtuple()
的带类型版本。用法
class Employee(NamedTuple): name: str id: int
这等价于:
Employee = collections.namedtuple('Employee', ['name', 'id'])
要为字段提供默认值,可以在类主体中为其赋值
class Employee(NamedTuple): name: str id: int = 3 employee = Employee('Guido') assert employee.id == 3
具有默认值的字段必须位于任何没有默认值的字段之后。
生成的类有一个额外的属性
__annotations__
,它给出了一个将字段名称映射到字段类型的字典。(字段名称在_fields
属性中,默认值在_field_defaults
属性中,这两个属性都是namedtuple()
API 的一部分。)NamedTuple
子类还可以有文档字符串和方法class Employee(NamedTuple): """Represents an employee.""" name: str id: int = 3 def __repr__(self) -> str: return f'<Employee {self.name}, id={self.id}>'
NamedTuple
子类可以是泛型的class Group[T](NamedTuple): key: T group: list[T]
向后兼容用法
# For creating a generic NamedTuple on Python 3.11 T = TypeVar("T") class Group(NamedTuple, Generic[T]): key: T group: list[T] # A functional syntax is also supported Employee = NamedTuple('Employee', [('name', str), ('id', int)])
3.6 版本中的变化: 添加了对 PEP 526 变量注解语法的支持。
3.6.1 版本中的变化: 添加了对默认值、方法和文档字符串的支持。
3.8 版本中的变化:
_field_types
和__annotations__
属性现在是普通字典而不是OrderedDict
的实例。3.9 版本中的变化: 删除了
_field_types
属性,取而代之的是更标准的__annotations__
属性,它包含相同的信息。3.11 版本中的变化: 添加了对泛型命名元组的支持。
自 3.13 版弃用,将在 3.15 版中移除: 用于创建 NamedTuple 类的未文档关键字参数语法 (
NT = NamedTuple("NT", x=int)
) 已弃用,并将在 3.15 中禁用。请改用基于类或函数式语法。自 3.13 版弃用,将在 3.15 版中移除: 在使用函数式语法创建 NamedTuple 类时,未向“fields”参数传递值 (
NT = NamedTuple("NT")
) 已弃用。向“fields”参数传递None
(NT = NamedTuple("NT", None)
) 也已弃用。两者都将在 Python 3.15 中禁用。要创建具有 0 个字段的 NamedTuple 类,请使用class NT(NamedTuple): pass
或NT = NamedTuple("NT", [])
。
- class typing.NewType(name, tp)¶
用于创建低开销 不同类型 的辅助类。
NewType
被类型检查器视为一种不同的类型。然而,在运行时,调用NewType
会返回其参数不变。用法
UserId = NewType('UserId', int) # Declare the NewType "UserId" first_user = UserId(1) # "UserId" returns the argument unchanged at runtime
- __module__¶
定义新类型的模块的名称。
- __name__¶
新类型的名称。
- __supertype__¶
新类型所基于的类型。
3.5.2 版本新增。
3.10 版本中的变化:
NewType
现在是一个类而不是一个函数。
- class typing.Protocol(Generic)¶
协议类的基类。
协议类定义如下
class Proto(Protocol): def meth(self) -> int: ...
此类主要与识别结构子类型(静态鸭子类型)的静态类型检查器一起使用,例如
class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check
有关更多详细信息,请参阅 PEP 544。用
runtime_checkable()
(稍后描述)装饰的协议类充当简单的运行时协议,仅检查给定属性的存在,而忽略其类型签名。没有此装饰器的协议类不能用作isinstance()
或issubclass()
的第二个参数。协议类可以是泛型的,例如
class GenProto[T](Protocol): def meth(self) -> T: ...
在需要与 Python 3.11 或更早版本兼容的代码中,泛型协议可以按如下方式编写
T = TypeVar("T") class GenProto(Protocol[T]): def meth(self) -> T: ...
在 3.8 版本加入。
- @typing.runtime_checkable¶
将协议类标记为运行时协议。
此协议可与
isinstance()
和issubclass()
一起使用。这允许进行简单的结构检查,这与collections.abc
中的“一招鲜”类似,例如Iterable
。例如@runtime_checkable class Closable(Protocol): def close(self): ... assert isinstance(open('/some/file'), Closable) @runtime_checkable class Named(Protocol): name: str import threading assert isinstance(threading.Thread(name='Bob'), Named)
当应用于非协议类时,此装饰器会引发
TypeError
。备注
runtime_checkable()
将仅检查所需方法或属性的存在,而不检查它们的类型签名或类型。例如,ssl.SSLObject
是一个类,因此它通过了issubclass()
对 Callable 的检查。但是,ssl.SSLObject.__init__
方法仅用于引发带有更具信息性消息的TypeError
,因此无法调用(实例化)ssl.SSLObject
。备注
与对非协议类的
isinstance()
检查相比,对运行时可检查协议的isinstance()
检查可能会出乎意料地慢。在性能敏感的代码中,请考虑使用hasattr()
调用等替代方案进行结构检查。在 3.8 版本加入。
3.12 版本中的变化: 针对运行时可检查协议的
isinstance()
检查的内部实现现在使用inspect.getattr_static()
来查找属性(以前使用hasattr()
)。因此,在 Python 3.12+ 上,某些过去被认为是运行时可检查协议实例的对象可能不再被认为是该协议的实例,反之亦然。大多数用户不太可能受到此更改的影响。3.12 版本中的变化: 运行时可检查协议的成员现在在类创建后立即在运行时被视为“冻结”。修补运行时可检查协议的属性仍然有效,但不会对比较对象与协议的
isinstance()
检查产生影响。有关更多详细信息,请参阅 Python 3.12 中的新特性。
- class typing.TypedDict(dict)¶
用于为字典添加类型提示的特殊构造。在运行时,它是一个普通的
dict
。TypedDict
声明了一个字典类型,它期望其所有实例都具有一组特定的键,其中每个键都与一致类型的值相关联。这种期望在运行时不会被检查,仅由类型检查器强制执行。用法class Point2D(TypedDict): x: int y: int label: str a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')
创建
TypedDict
的另一种方法是使用函数调用语法。第二个参数必须是一个字面dict
Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})
此函数式语法允许定义非有效 标识符 的键,例如因为它们是关键字或包含连字符,或者当键名不能像常规私有名称一样被 损坏 时
# raises SyntaxError class Point2D(TypedDict): in: int # 'in' is a keyword x-y: int # name with hyphens class Definition(TypedDict): __schema: str # mangled to `_Definition__schema` # OK, functional syntax Point2D = TypedDict('Point2D', {'in': int, 'x-y': int}) Definition = TypedDict('Definition', {'__schema': str}) # not mangled
默认情况下,所有键都必须存在于
TypedDict
中。可以使用NotRequired
将单个键标记为非必需class Point2D(TypedDict): x: int y: int label: NotRequired[str] # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': NotRequired[str]})
这意味着
Point2D
TypedDict
可以省略label
键。也可以通过指定
False
的总量来默认将所有键标记为非必需class Point2D(TypedDict, total=False): x: int y: int # Alternative syntax Point2D = TypedDict('Point2D', {'x': int, 'y': int}, total=False)
这意味着
Point2D
TypedDict
可以省略任何键。类型检查器仅期望支持字面值False
或True
作为total
参数的值。True
是默认值,并使类主体中定义的所有项成为必需项。total=False
TypedDict
的单个键可以使用Required
标记为必需class Point2D(TypedDict, total=False): x: Required[int] y: Required[int] label: str # Alternative syntax Point2D = TypedDict('Point2D', { 'x': Required[int], 'y': Required[int], 'label': str }, total=False)
TypedDict
类型可以使用基于类的语法继承一个或多个其他TypedDict
类型。用法class Point3D(Point2D): z: int
Point3D
有三个项:x
、y
和z
。这等同于此定义class Point3D(TypedDict): x: int y: int z: int
一个
TypedDict
不能从非TypedDict
类继承,除了Generic
。例如class X(TypedDict): x: int class Y(TypedDict): y: int class Z(object): pass # A non-TypedDict class class XY(X, Y): pass # OK class XZ(X, Z): pass # raises TypeError
一个
TypedDict
可以是泛型的class Group[T](TypedDict): key: T group: list[T]
要创建与 Python 3.11 或更低版本兼容的泛型
TypedDict
,请显式继承自Generic
T = TypeVar("T") class Group(TypedDict, Generic[T]): key: T group: list[T]
TypedDict
可以通过注解字典(有关注解最佳实践的更多信息,请参阅 注解最佳实践)、__total__
、__required_keys__
和__optional_keys__
进行内省。- __total__¶
Point2D.__total__
给出total
参数的值。示例>>> from typing import TypedDict >>> class Point2D(TypedDict): pass >>> Point2D.__total__ True >>> class Point2D(TypedDict, total=False): pass >>> Point2D.__total__ False >>> class Point3D(Point2D): pass >>> Point3D.__total__ True
此属性 *仅* 反映当前
TypedDict
类的total
参数值,而不是该类是否在语义上是完整的。例如,一个__total__
设置为True
的TypedDict
可能具有用NotRequired
标记的键,或者它可能继承自另一个TypedDict
,其total=False
。因此,通常最好使用__required_keys__
和__optional_keys__
进行内省。
- __required_keys__¶
在 3.9 版本中新增。
- __optional_keys__¶
Point2D.__required_keys__
和Point2D.__optional_keys__
分别返回包含必需键和非必需键的frozenset
对象。标记为
Required
的键将始终出现在__required_keys__
中,标记为NotRequired
的键将始终出现在__optional_keys__
中。为了向后兼容 Python 3.10 及更早版本,还可以使用继承在同一个
TypedDict
中同时声明必需键和非必需键。这通过声明一个TypedDict
,其total
参数有一个值,然后在其另一个TypedDict
中继承它,该TypedDict
的total
具有不同的值>>> class Point2D(TypedDict, total=False): ... x: int ... y: int ... >>> class Point3D(Point2D): ... z: int ... >>> Point3D.__required_keys__ == frozenset({'z'}) True >>> Point3D.__optional_keys__ == frozenset({'x', 'y'}) True
在 3.9 版本中新增。
备注
如果使用
from __future__ import annotations
或将注解作为字符串提供,则在定义TypedDict
时不会评估注解。因此,__required_keys__
和__optional_keys__
依赖的运行时内省可能无法正常工作,并且属性值可能不正确。
对
ReadOnly
的支持反映在以下属性中有关更多示例和详细规则,请参阅类型文档中的 TypedDict 部分。
在 3.8 版本加入。
3.11 版本中的变化: 添加了对将单个键标记为
Required
或NotRequired
的支持。请参阅 PEP 655。版本 3.11 中的变化: 添加了对泛型
TypedDict
的支持。版本 3.13 中的变化: 移除了通过关键字参数方法创建
TypedDict
的支持。版本 3.13 中的变化: 添加了对
ReadOnly
限定符的支持。自 3.13 版本弃用,将在 3.15 版本中移除: 当使用函数式语法创建 TypedDict 类时,未能向 'fields' 参数传递值 (
TD = TypedDict("TD")
) 已被弃用。向 'fields' 参数传递None
(TD = TypedDict("TD", None)
) 也已被弃用。两者都将在 Python 3.15 中被禁止。要创建一个包含 0 个字段的 TypedDict 类,请使用class TD(TypedDict): pass
或TD = TypedDict("TD", {})
。
协议¶
typing
模块提供了以下协议。所有协议都用 @runtime_checkable
装饰。
- class typing.SupportsAbs¶
一个 ABC,带有一个抽象方法
__abs__
,其返回类型是协变的。
- class typing.SupportsBytes¶
一个 ABC,带有一个抽象方法
__bytes__
。
- class typing.SupportsComplex¶
一个 ABC,带有一个抽象方法
__complex__
。
- class typing.SupportsFloat¶
一个 ABC,带有一个抽象方法
__float__
。
- class typing.SupportsIndex¶
一个 ABC,带有一个抽象方法
__index__
。在 3.8 版本加入。
- class typing.SupportsInt¶
一个 ABC,带有一个抽象方法
__int__
。
- class typing.SupportsRound¶
一个 ABC,带有一个抽象方法
__round__
,其返回类型是协变的。
用于处理 I/O 的 ABC 和协议¶
- class typing.IO[AnyStr]¶
- class typing.TextIO[AnyStr]¶
- class typing.BinaryIO[AnyStr]¶
泛型类
IO[AnyStr]
及其子类TextIO(IO[str])
和BinaryIO(IO[bytes])
表示 I/O 流的类型,例如由open()
返回的流。请注意,这些类不是协议,它们的接口相当广泛。
协议 io.Reader
和 io.Writer
为参数类型提供了更简单的替代方案,分别仅在访问 read()
或 write()
方法时使用
def read_and_write(reader: Reader[str], writer: Writer[bytes]):
data = reader.read()
writer.write(data.encode())
还可以考虑使用 collections.abc.Iterable
来迭代输入流的行
def read_config(stream: Iterable[str]):
for line in stream:
...
函数和装饰器¶
- typing.cast(typ, val)¶
将值强制转换为某种类型。
这会原样返回该值。对于类型检查器来说,这表示返回值具有指定的类型,但在运行时我们有意不检查任何内容(我们希望它尽可能快)。
- typing.assert_type(val, typ, /)¶
要求静态类型检查器确认 val 的推断类型为 typ。
在运行时,这不做任何事情:它返回第一个参数不变,没有检查或副作用,无论参数的实际类型是什么。
当静态类型检查器遇到对
assert_type()
的调用时,如果值不是指定类型,它会发出错误def greet(name: str) -> None: assert_type(name, str) # OK, inferred type of `name` is `str` assert_type(name, int) # type checker error
此函数有助于确保类型检查器对脚本的理解与开发者的意图一致
def complex_function(arg: object): # Do some complex type-narrowing logic, # after which we hope the inferred type will be `int` ... # Test whether the type checker correctly understands our function assert_type(arg, int)
在 3.11 版本中新增。
- typing.assert_never(arg, /)¶
要求静态类型检查器确认某行代码无法访问。
示例
def int_or_str(arg: int | str) -> None: match arg: case int(): print("It's an int") case str(): print("It's a str") case _ as unreachable: assert_never(unreachable)
在这里,注解允许类型检查器推断出最后一个 case 永远不会执行,因为
arg
要么是int
要么是str
,并且这两个选项都被前面的 case 覆盖了。如果类型检查器发现对
assert_never()
的调用是可达的,它将发出错误。例如,如果arg
的类型注解是int | str | float
,则类型检查器将发出错误,指出unreachable
的类型是float
。要使对assert_never
的调用通过类型检查,传入参数的推断类型必须是底部类型Never
,而不是其他任何类型。在运行时,当调用此函数时会引发异常。
参见
不可达代码和穷尽性检查 提供了有关使用静态类型进行穷尽性检查的更多信息。
在 3.11 版本中新增。
- typing.reveal_type(obj, /)¶
要求静态类型检查器显示表达式的推断类型。
当静态类型检查器遇到对此函数的调用时,它会发出一个带有参数推断类型的诊断。例如
x: int = 1 reveal_type(x) # Revealed type is "builtins.int"
当您想调试类型检查器如何处理特定代码时,这会很有用。
在运行时,此函数将其参数的运行时类型打印到
sys.stderr
并原样返回参数(允许在表达式中使用该调用)x = reveal_type(1) # prints "Runtime type is int" print(x) # prints "1"
请注意,运行时类型可能与(更具体或不那么具体于)类型检查器静态推断的类型不同。
大多数类型检查器都支持在任何地方使用
reveal_type()
,即使该名称没有从typing
导入。然而,从typing
导入该名称可以使您的代码在运行时不会出现错误,并更清楚地传达意图。在 3.11 版本中新增。
- @typing.dataclass_transform(*, eq_default=True, order_default=False, kw_only_default=False, frozen_default=False, field_specifiers=(), **kwargs)¶
标记对象提供
dataclass
-like 行为的装饰器。dataclass_transform
可用于装饰类、元类或本身是装饰器的函数。@dataclass_transform()
的存在告诉静态类型检查器,被装饰对象执行运行时“魔术”,以类似于@dataclasses.dataclass
的方式转换类。装饰器函数的使用示例
@dataclass_transform() def create_model[T](cls: type[T]) -> type[T]: ... return cls @create_model class CustomerModel: id: int name: str
在基类上
@dataclass_transform() class ModelBase: ... class CustomerModel(ModelBase): id: int name: str
在元类上
@dataclass_transform() class ModelMeta(type): ... class ModelBase(metaclass=ModelMeta): ... class CustomerModel(ModelBase): id: int name: str
上面定义的
CustomerModel
类将被类型检查器处理,类似于使用@dataclasses.dataclass
创建的类。例如,类型检查器将假定这些类具有接受id
和name
的__init__
方法。被装饰的类、元类或函数可以接受以下布尔参数,类型检查器将假定它们具有与
@dataclasses.dataclass
装饰器相同的效果:init
、eq
、order
、unsafe_hash
、frozen
、match_args
、kw_only
和slots
。这些参数的值(True
或False
)必须能够被静态评估。dataclass_transform
装饰器的参数可用于自定义被装饰类、元类或函数的默认行为- 参数:
eq_default (bool) – 指示如果调用者省略
eq
参数,则其值应假定为True
还是False
。默认为True
。order_default (bool) – 指示如果调用者省略
order
参数,则其值应假定为True
还是False
。默认为False
。kw_only_default (bool) – 指示如果调用者省略
kw_only
参数,则其值应假定为True
还是False
。默认为False
。frozen_default (bool) –
指示如果调用者省略
frozen
参数,则其值应假定为True
还是False
。默认为False
。3.12 新版功能.
field_specifiers (tuple[Callable[..., Any], ...]) – 指定支持的类或函数的静态列表,用于描述字段,类似于
dataclasses.field()
。默认为()
。**kwargs (Any) – 接受任意其他关键字参数,以允许可能的未来扩展。
类型检查器识别字段说明符上的以下可选参数
字段说明符的识别参数¶ 参数名称
描述
init
指示字段是否应包含在合成的
__init__
方法中。如果未指定,init
默认为True
。default
提供字段的默认值。
default_factory
提供一个运行时回调,返回字段的默认值。如果
default
和default_factory
均未指定,则假定该字段没有默认值,并且在实例化类时必须提供一个值。factory
字段说明符上
default_factory
参数的别名。kw_only
指示字段是否应标记为仅限关键字参数。如果为
True
,则该字段将为仅限关键字参数。如果为False
,则它将不是仅限关键字参数。如果未指定,则使用用dataclass_transform
装饰的对象上的kw_only
参数的值,或者如果该参数未指定,则使用dataclass_transform
上的kw_only_default
值。alias
为字段提供一个替代名称。此替代名称用于合成的
__init__
方法。在运行时,此装饰器将其参数记录在被装饰对象的
__dataclass_transform__
属性中。它没有其他运行时效果。有关更多详细信息,请参阅 PEP 681。
在 3.11 版本中新增。
- @typing.overload¶
用于创建重载函数和方法的装饰器。
@overload 装饰器允许描述支持多种不同参数类型组合的函数和方法。一系列 @overload 装饰的定义之后必须紧跟一个未被 @overload 装饰的定义(针对同一个函数/方法)。
@overload
装饰的定义仅用于类型检查器,因为它们将被非@overload
装饰的定义覆盖。同时,非@overload
装饰的定义将在运行时使用,但应被类型检查器忽略。在运行时,直接调用@overload
装饰的函数将引发NotImplementedError
。一个重载示例,它提供了比使用 union 或类型变量表达更精确的类型
@overload def process(response: None) -> None: ... @overload def process(response: int) -> tuple[int, str]: ... @overload def process(response: bytes) -> str: ... def process(response): ... # actual implementation goes here
有关更多详细信息以及与其他类型语义的比较,请参阅 PEP 484。
版本 3.11 中的变化: 现在可以使用
get_overloads()
在运行时内省重载函数。
- typing.get_overloads(func)¶
返回 func 的
@overload
装饰定义序列。func 是重载函数实现的函数对象。例如,给定
@overload
文档中的process
定义,get_overloads(process)
将返回三个已定义重载的三个函数对象序列。如果对没有重载的函数调用,get_overloads()
返回一个空序列。get_overloads()
可用于在运行时内省重载函数。在 3.11 版本中新增。
- typing.clear_overloads()¶
清除内部注册表中的所有已注册重载。
这可用于回收注册表使用的内存。
在 3.11 版本中新增。
- @typing.final¶
指示最终方法和最终类的装饰器。
使用
@final
装饰方法向类型检查器指示该方法不能在子类中被覆盖。使用@final
装饰类指示它不能被子类化。例如:
class Base: @final def done(self) -> None: ... class Sub(Base): def done(self) -> None: # Error reported by type checker ... @final class Leaf: ... class Other(Leaf): # Error reported by type checker ...
这些属性没有运行时检查。有关更多详细信息,请参阅 PEP 591。
在 3.8 版本加入。
版本 3.11 中的变化: 装饰器现在将尝试在被装饰对象上将
__final__
属性设置为True
。因此,在运行时可以使用诸如if getattr(obj, "__final__", False)
这样的检查来确定对象obj
是否已被标记为 final。如果被装饰对象不支持设置属性,则装饰器将返回未更改的对象,而不引发异常。
- @typing.no_type_check¶
指示注解不是类型提示的装饰器。
这作为类或函数 装饰器 起作用。对于类,它递归地应用于该类中定义的所有方法和类(但不适用于其超类或子类中定义的方法)。类型检查器将忽略带有此装饰器的函数或类中的所有注解。
@no_type_check
会就地修改被装饰对象。
- @typing.no_type_check_decorator¶
一个装饰器,用于赋予另一个装饰器
no_type_check()
效果。这会将装饰器封装在一个东西中,该东西又将装饰的函数封装在
no_type_check()
中。自 3.13 版本弃用,将在 3.15 版本中移除: 没有任何类型检查器曾添加对
@no_type_check_decorator
的支持。因此,它已被弃用,并将在 Python 3.15 中移除。
- @typing.override¶
指示子类中的方法旨在覆盖超类中的方法或属性的装饰器。
类型检查器应在用
@override
装饰的方法实际上没有覆盖任何内容时发出错误。这有助于防止在更改基类而子类没有相应更改时可能发生的错误。例如:
class Base: def log_status(self) -> None: ... class Sub(Base): @override def log_status(self) -> None: # Okay: overrides Base.log_status ... @override def done(self) -> None: # Error reported by type checker ...
此属性没有运行时检查。
装饰器将尝试在被装饰对象上将
__override__
属性设置为True
。因此,可以在运行时使用诸如if getattr(obj, "__override__", False)
的检查来确定对象obj
是否已被标记为覆盖。如果被装饰对象不支持设置属性,装饰器将返回未更改的对象而不引发异常。有关更多详细信息,请参阅 PEP 698。
3.12 新版功能.
- @typing.type_check_only¶
标记类或函数在运行时不可用的装饰器。
这个装饰器本身在运行时不可用。它主要用于标记在类型存根文件中定义的类,如果实现返回私有类的实例
@type_check_only class Response: # private or not available at runtime code: int def get_header(self, name: str) -> str: ... def fetch_response() -> Response: ...
请注意,不建议返回私有类的实例。通常更倾向于将此类类公开。
内省助手¶
- typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)¶
返回包含函数、方法、模块或类对象的类型提示的字典。
这通常与
obj.__annotations__
相同,但此函数对注解字典进行以下更改通过在 globalns、localns 以及(适用时)obj 的 type parameter 命名空间中评估,处理编码为字符串字面量或
ForwardRef
对象的正向引用。如果未给出 globalns 或 localns,则从 obj 推断适当的命名空间字典。None
被替换为types.NoneType
。如果
@no_type_check
已应用于 obj,则返回一个空字典。如果 obj 是类
C
,则该函数返回一个字典,该字典将C
的基类中的注解与C
上直接的注解合并。这是通过遍历C.__mro__
并迭代组合__annotations__
字典来完成的。在 方法解析顺序 中较早出现的类上的注解总是优先于在方法解析顺序中较晚出现的类上的注解。该函数递归地将所有
Annotated[T, ...]
的出现替换为T
,除非 include_extras 设置为True
(有关更多信息,请参阅Annotated
)。
另请参阅
annotationlib.get_annotations()
,这是一个更底层的函数,它更直接地返回注解。注意
此函数可能会执行注解中包含的任意代码。有关更多信息,请参阅 内省注解的安全影响。
备注
如果 obj 的注解中的任何前向引用无法解析或不是有效的 Python 代码,此函数将引发异常,例如
NameError
。例如,这可能发生在包含前向引用的导入 类型别名 或在if TYPE_CHECKING
下导入的名称。版本 3.11 中的变化: 以前,如果设置了等于
None
的默认值,则会为函数和方法注解添加Optional[t]
。现在,注解原样返回。
- typing.get_origin(tp)¶
获取类型的未下标版本:对于
X[Y, Z, ...]
形式的 typing 对象,返回X
。如果
X
是内置类或collections
类的 typing 模块别名,它将被规范化为原始类。如果X
是ParamSpecArgs
或ParamSpecKwargs
的实例,则返回底层ParamSpec
。对于不支持的对象,返回None
。示例:
assert get_origin(str) is None assert get_origin(Dict[str, int]) is dict assert get_origin(Union[int, str]) is Union assert get_origin(Annotated[str, "metadata"]) is Annotated P = ParamSpec('P') assert get_origin(P.args) is P assert get_origin(P.kwargs) is P
在 3.8 版本加入。
- typing.get_args(tp)¶
获取所有替换已执行的类型参数:对于
X[Y, Z, ...]
形式的 typing 对象,返回(Y, Z, ...)
。如果
X
是包含在另一个泛型类型中的 union 或Literal
,则(Y, Z, ...)
的顺序可能与原始参数[Y, Z, ...]
的顺序不同,这是由于类型缓存。对于不支持的对象,返回()
。示例:
assert get_args(int) == () assert get_args(Dict[int, str]) == (int, str) assert get_args(Union[int, str]) == (int, str)
在 3.8 版本加入。
- typing.get_protocol_members(tp)¶
返回
Protocol
中定义的成员集合。>>> from typing import Protocol, get_protocol_members >>> class P(Protocol): ... def a(self) -> str: ... ... b: int >>> get_protocol_members(P) == frozenset({'a', 'b'}) True
对于不是协议的参数,引发
TypeError
。在 3.13 版本加入。
- typing.is_protocol(tp)¶
判断一个类型是否为
Protocol
。例如:
class P(Protocol): def a(self) -> str: ... b: int is_protocol(P) # => True is_protocol(int) # => False
在 3.13 版本加入。
- typing.is_typeddict(tp)¶
检查一个类型是否为
TypedDict
。例如:
class Film(TypedDict): title: str year: int assert is_typeddict(Film) assert not is_typeddict(list | str) # TypedDict is a factory for creating typed dicts, # not a typed dict itself assert not is_typeddict(TypedDict)
在 3.10 版本加入。
- class typing.ForwardRef¶
用于字符串前向引用的内部类型表示的类。
例如,
List["SomeClass"]
被隐式转换为List[ForwardRef("SomeClass")]
。ForwardRef
不应由用户实例化,但可由内省工具使用。备注
PEP 585 泛型类型(例如
list["SomeClass"]
)不会隐式转换为list[ForwardRef("SomeClass")]
,因此不会自动解析为list[SomeClass]
。3.7.4 版本新增。
版本 3.14 中的变化: 这现在是
annotationlib.ForwardRef
的别名。此类的几个未文档行为已更改;例如,在评估ForwardRef
之后,评估值不再缓存。
- typing.evaluate_forward_ref(forward_ref, *, owner=None, globals=None, locals=None, type_params=None, format=annotationlib.Format.VALUE)¶
将
annotationlib.ForwardRef
评估为 类型提示。这类似于调用
annotationlib.ForwardRef.evaluate()
,但与该方法不同,evaluate_forward_ref()
还会递归地评估类型提示中嵌套的前向引用。有关 owner、globals、locals、type_params 和 format 参数的含义,请参阅
annotationlib.ForwardRef.evaluate()
的文档。注意
此函数可能会执行注解中包含的任意代码。有关更多信息,请参阅 内省注解的安全影响。
在 3.14 版本加入。
- typing.NoDefault¶
一个哨兵对象,用于指示类型参数没有默认值。例如
>>> T = TypeVar("T") >>> T.__default__ is typing.NoDefault True >>> S = TypeVar("S", default=None) >>> S.__default__ is None True
在 3.13 版本加入。
常量¶
- typing.TYPE_CHECKING¶
一个特殊常量,被第三方静态类型检查器假定为
True
。它在运行时为False
。一个导入开销大,且仅包含用于类型注解的类型的模块,可以安全地导入在
if TYPE_CHECKING:
块中。这阻止了该模块在运行时实际导入;注解不会急切地评估(参见 PEP 649),因此在注解中使用未定义的符号是无害的——只要您以后不检查它们。您的静态类型分析工具将在静态类型分析期间将TYPE_CHECKING
设置为True
,这意味着该模块将被导入,并且在这样的分析期间类型将被正确检查。用法
if TYPE_CHECKING: import expensive_mod def fun(arg: expensive_mod.SomeType) -> None: local_var: expensive_mod.AnotherType = other_fun()
如果您偶尔需要在运行时检查可能包含未定义符号的类型注解,请使用
annotationlib.get_annotations()
并将format
参数设置为annotationlib.Format.STRING
或annotationlib.Format.FORWARDREF
,以安全地检索注解而不会引发NameError
。3.5.2 版本新增。
已弃用的别名¶
此模块定义了几个已弃用的别名,指向预先存在的标准库类。这些别名最初包含在 typing
模块中,以支持使用 []
对这些泛型类进行参数化。然而,在 Python 3.9 中,当相应的预先存在的类被增强以支持 []
时(参见 PEP 585),这些别名变得多余。
这些冗余类型自 Python 3.9 起已弃用。但是,虽然这些别名可能会在某个时候被删除,但目前没有计划删除它们。因此,解释器目前不会为这些别名发出弃用警告。
如果在某个时候决定删除这些已弃用的别名,解释器将在删除前至少两个版本发出弃用警告。这些别名保证在 typing
模块中保留,且不发出弃用警告,直到至少 Python 3.14。
建议类型检查器在程序目标最小 Python 版本为 3.9 或更高版本时,标记已弃用类型的使用。
内置类型的别名¶
- class typing.Dict(dict, MutableMapping[KT, VT])¶
已弃用的
dict
别名。请注意,为了注解参数,最好使用抽象集合类型(如
Mapping
),而不是使用dict
或typing.Dict
。自 3.9 版本弃用:
builtins.dict
现在支持下标([]
)。请参阅 PEP 585 和 泛型别名类型。
- class typing.List(list, MutableSequence[T])¶
已弃用的
list
别名。请注意,为了注解参数,最好使用抽象集合类型(如
Sequence
或Iterable
),而不是使用list
或typing.List
。自 3.9 版本弃用:
builtins.list
现在支持下标([]
)。请参阅 PEP 585 和 泛型别名类型。
- class typing.Set(set, MutableSet[T])¶
已弃用的
builtins.set
别名。请注意,为了注解参数,最好使用抽象集合类型(如
collections.abc.Set
),而不是使用set
或typing.Set
。自 3.9 版本弃用:
builtins.set
现在支持下标([]
)。请参阅 PEP 585 和 泛型别名类型。
- class typing.FrozenSet(frozenset, AbstractSet[T_co])¶
已弃用的
builtins.frozenset
别名。自 3.9 版本弃用:
builtins.frozenset
现在支持下标([]
)。请参阅 PEP 585 和 泛型别名类型。
collections
中类型的别名¶
- class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])¶
已弃用的
collections.defaultdict
别名。3.5.2 版本新增。
自 3.9 版本弃用:
collections.defaultdict
现在支持下标([]
)。请参阅 PEP 585 和 泛型别名类型。
- class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])¶
已弃用的
collections.OrderedDict
别名。3.7.2 版本新增。
自 3.9 版本弃用:
collections.OrderedDict
现在支持下标([]
)。请参阅 PEP 585 和 泛型别名类型。
- class typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT])¶
已弃用的
collections.ChainMap
别名。3.6.1 版本新增。
自 3.9 版本弃用:
collections.ChainMap
现在支持下标([]
)。请参阅 PEP 585 和 泛型别名类型。
- class typing.Counter(collections.Counter, Dict[T, int])¶
已弃用的
collections.Counter
别名。3.6.1 版本新增。
自 3.9 版本弃用:
collections.Counter
现在支持下标([]
)。请参阅 PEP 585 和 泛型别名类型。
- class typing.Deque(deque, MutableSequence[T])¶
已弃用的
collections.deque
别名。3.6.1 版本新增。
自 3.9 版本弃用:
collections.deque
现在支持下标([]
)。请参阅 PEP 585 和 泛型别名类型。
其他具体类型的别名¶
- class typing.Pattern¶
- class typing.Match¶
已弃用的别名,对应于
re.compile()
和re.match()
的返回类型。这些类型(和相应的函数)是泛型于
AnyStr
的。Pattern
可以特化为Pattern[str]
或Pattern[bytes]
;Match
可以特化为Match[str]
或Match[bytes]
。
- class typing.Text¶
str
的弃用别名。提供
Text
是为了给 Python 2 代码提供一个向前兼容的路径:在 Python 2 中,Text
是unicode
的别名。使用
Text
来表示一个值必须包含一个与 Python 2 和 Python 3 都兼容的 unicode 字符串。def add_unicode_checkmark(text: Text) -> Text: return text + u' \u2713'
3.5.2 版本新增。
自 3.11 版本弃用: Python 2 已不再受支持,并且大多数类型检查器也不再支持对 Python 2 代码进行类型检查。目前没有计划移除此别名,但鼓励用户使用
str
而不是Text
。
collections.abc
中的容器抽象基类的别名¶
- class typing.AbstractSet(Collection[T_co])¶
collections.abc.Set
的弃用别名。自 3.9 版本弃用:
collections.abc.Set
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.ByteString(Sequence[int])¶
collections.abc.ByteString
的弃用别名。在运行时,使用
isinstance(obj, collections.abc.Buffer)
来测试obj
是否实现了缓冲区协议。在类型注解中,可以使用Buffer
或显式指定代码支持的类型的联合(例如,bytes | bytearray | memoryview
)。ByteString
最初旨在成为一个抽象类,它将作为bytes
和bytearray
的超类型。然而,由于这个 ABC 从未有任何方法,因此知道一个对象是ByteString
的实例实际上并未提供任何有用的信息。其他常见的缓冲区类型,如memoryview
,也从未被视为ByteString
的子类型(无论是运行时还是静态类型检查器)。更多详情请参见 PEP 688。
自 3.9 版本弃用,将于 3.17 版本移除。
- class typing.Collection(Sized, Iterable[T_co], Container[T_co])¶
collections.abc.Collection
的弃用别名。在 3.6 版本加入。
自 3.9 版本弃用:
collections.abc.Collection
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.Container(Generic[T_co])¶
collections.abc.Container
的弃用别名。自 3.9 版本弃用:
collections.abc.Container
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.ItemsView(MappingView, AbstractSet[tuple[KT_co, VT_co]])¶
collections.abc.ItemsView
的弃用别名。自 3.9 版本弃用:
collections.abc.ItemsView
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.KeysView(MappingView, AbstractSet[KT_co])¶
collections.abc.KeysView
的弃用别名。自 3.9 版本弃用:
collections.abc.KeysView
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.Mapping(Collection[KT], Generic[KT, VT_co])¶
collections.abc.Mapping
的弃用别名。自 3.9 版本弃用:
collections.abc.Mapping
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.MappingView(Sized)¶
collections.abc.MappingView
的弃用别名。自 3.9 版本弃用:
collections.abc.MappingView
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.MutableMapping(Mapping[KT, VT])¶
collections.abc.MutableMapping
的弃用别名。自 3.9 版本弃用:
collections.abc.MutableMapping
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.MutableSequence(Sequence[T])¶
collections.abc.MutableSequence
的弃用别名。自 3.9 版本弃用:
collections.abc.MutableSequence
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.MutableSet(AbstractSet[T])¶
collections.abc.MutableSet
的弃用别名。自 3.9 版本弃用:
collections.abc.MutableSet
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.Sequence(Reversible[T_co], Collection[T_co])¶
collections.abc.Sequence
的弃用别名。自 3.9 版本弃用:
collections.abc.Sequence
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.ValuesView(MappingView, Collection[_VT_co])¶
collections.abc.ValuesView
的弃用别名。自 3.9 版本弃用:
collections.abc.ValuesView
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
collections.abc
中的异步抽象基类的别名¶
- class typing.Coroutine(Awaitable[ReturnType], Generic[YieldType, SendType, ReturnType])¶
collections.abc.Coroutine
的弃用别名。有关在类型注解中使用
collections.abc.Coroutine
和typing.Coroutine
的详细信息,请参见 注解生成器和协程。3.5.3 版本新增。
自 3.9 版本弃用:
collections.abc.Coroutine
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.AsyncGenerator(AsyncIterator[YieldType], Generic[YieldType, SendType])¶
collections.abc.AsyncGenerator
的弃用别名。有关在类型注解中使用
collections.abc.AsyncGenerator
和typing.AsyncGenerator
的详细信息,请参见 注解生成器和协程。3.6.1 版本新增。
自 3.9 版本弃用:
collections.abc.AsyncGenerator
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。3.13 版本中的变化:
SendType
参数现在有默认值。
- class typing.AsyncIterable(Generic[T_co])¶
collections.abc.AsyncIterable
的弃用别名。3.5.2 版本新增。
自 3.9 版本弃用:
collections.abc.AsyncIterable
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.AsyncIterator(AsyncIterable[T_co])¶
collections.abc.AsyncIterator
的弃用别名。3.5.2 版本新增。
自 3.9 版本弃用:
collections.abc.AsyncIterator
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.Awaitable(Generic[T_co])¶
collections.abc.Awaitable
的弃用别名。3.5.2 版本新增。
自 3.9 版本弃用:
collections.abc.Awaitable
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
collections.abc
中其他抽象基类的别名¶
- class typing.Iterable(Generic[T_co])¶
collections.abc.Iterable
的弃用别名。自 3.9 版本弃用:
collections.abc.Iterable
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.Iterator(Iterable[T_co])¶
collections.abc.Iterator
的弃用别名。自 3.9 版本弃用:
collections.abc.Iterator
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- typing.Callable¶
collections.abc.Callable
的弃用别名。有关如何在类型注解中使用
collections.abc.Callable
和typing.Callable
的详细信息,请参见 注解可调用对象。自 3.9 版本弃用:
collections.abc.Callable
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。3.10 版本中的变化:
Callable
现在支持ParamSpec
和Concatenate
。更多详情请参见 PEP 612。
- class typing.Generator(Iterator[YieldType], Generic[YieldType, SendType, ReturnType])¶
collections.abc.Generator
的弃用别名。有关在类型注解中使用
collections.abc.Generator
和typing.Generator
的详细信息,请参见 注解生成器和协程。自 3.9 版本弃用:
collections.abc.Generator
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。3.13 版本中的变化: 添加了发送和返回类型的默认值。
- class typing.Hashable¶
collections.abc.Hashable
的弃用别名。自 3.12 版本弃用: 请直接使用
collections.abc.Hashable
。
- class typing.Reversible(Iterable[T_co])¶
collections.abc.Reversible
的弃用别名。自 3.9 版本弃用:
collections.abc.Reversible
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。
- class typing.Sized¶
collections.abc.Sized
的弃用别名。自 3.12 版本弃用: 请直接使用
collections.abc.Sized
。
contextlib
抽象基类的别名¶
- class typing.ContextManager(Generic[T_co, ExitT_co])¶
contextlib.AbstractContextManager
的弃用别名。第一个类型参数
T_co
代表由__enter__()
方法返回的类型。可选的第二个类型参数ExitT_co
(默认为bool | None
)代表由__exit__()
方法返回的类型。在 3.5.4 版本中新增。
自 3.9 版本弃用:
contextlib.AbstractContextManager
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。3.13 版本中的变化: 添加了可选的第二个类型参数
ExitT_co
。
- class typing.AsyncContextManager(Generic[T_co, AExitT_co])¶
contextlib.AbstractAsyncContextManager
的弃用别名。第一个类型参数
T_co
代表由__aenter__()
方法返回的类型。可选的第二个类型参数AExitT_co
(默认为bool | None
)代表由__aexit__()
方法返回的类型。在 3.6.2 版本中新增。
自 3.9 版本弃用:
contextlib.AbstractAsyncContextManager
现在支持下标 ([]
)。参见 PEP 585 和 泛型别名类型。3.13 版本中的变化: 添加了可选的第二个类型参数
AExitT_co
。
主要功能弃用时间表¶
typing
中的某些功能已弃用,并可能在未来版本的 Python 中移除。下表总结了主要的弃用功能,以方便查阅。此表可能会有变动,并非所有弃用功能都已列出。
功能 |
弃用版本 |
预计移除版本 |
PEP/问题 |
---|---|---|---|
|
3.9 |
未定(详见 弃用别名) |
|
3.9 |
3.17 |
||
3.11 |
未定 |
||
3.12 |
未定 |
||
3.12 |
未定 |
||
3.13 |
3.15 |
||
3.13 |
3.18 |