typing ---支持类型提示

3.5 新版功能.

源代码: Lib/typing.py

注解

Python运行时不强制执行函数和变量类型注释。它们可以被第三方工具使用,如类型检查、ide、linter等。


此模块为由指定的类型提示提供运行时支持 PEP 484PEP 526PEP 544PEP 586PEP 589PEP 591PEP 612PEP 613 。最基本的支持由以下类型组成 AnyUnionTupleCallableTypeVar ,以及 Generic 。有关完整规格,请参阅 PEP 484 。有关类型提示的简化介绍,请参见 PEP 483

下面的函数接受并返回一个字符串,注释如下:

def greeting(name: str) -> str:
    return 'Hello ' + name

在函数中 greeting 参数 name 应为类型 str 以及返回类型 str . 子类型被接受为参数。

类型别名

类型别名是通过将类型分配给别名来定义的。在这个例子中, Vectorlist[float] 将被视为可互换的同义词:

Vector = list[float]

def scale(scalar: float, vector: Vector) -> Vector:
    return [scalar * num for num in vector]

# typechecks; a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])

类型别名对于简化复杂类型签名很有用。例如::

from collections.abc import Sequence

ConnectionOptions = dict[str, str]
Address = tuple[str, int]
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:
    ...

注意 None 由于类型提示是一种特殊情况,因此被替换为 type(None) .

NewType

使用 NewType() 用于创建不同类型的helper函数::

from typing import NewType

UserId = NewType('UserId', int)
some_id = UserId(524313)

静态类型检查器会将新类型视为原始类型的子类。这有助于捕获逻辑错误:

def get_user_name(user_id: UserId) -> str:
    ...

# typechecks
user_a = get_user_name(UserId(42351))

# does not typecheck; an int is not a UserId
user_b = get_user_name(-1)

你仍然可以表演所有 int 对类型变量的操作 UserId ,但结果始终为类型 int .这让你通过 UserId 无论何处 int 可能是预期的,但会阻止您意外创建 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 typecheck
class AdminUserId(UserId): pass

但是,可以创建一个 NewType() 基于“派生” NewType ::

from typing import NewType

UserId = NewType('UserId', int)

ProUserId = NewType('ProUserId', UserId)

和排版检查 ProUserId 将按预期工作。

PEP 484 了解更多详细信息。

注解

回想一下,使用类型别名将两个类型声明为 相等的 彼此之间。做 Alias = Original 将使静态类型检查器处理 Alias 作为 完全等效Original 在所有情况下。当您想要简化复杂类型签名时,这很有用。

相反, NewType 声明一个类型为 subtype 另一个。做 Derived = NewType('Derived', Original) 将使静态类型检查器处理 Derived 作为一个 子类 属于 Original ,表示类型的值 Original 不能在类型为的值所在的位置使用 Derived 是意料之中的事。当您希望以最低的运行时成本防止逻辑错误时,这是非常有用的。

3.5.2 新版功能.

可赎回的

需要特定签名的回调函数的框架可以使用 Callable[[Arg1Type, Arg2Type], ReturnType] .

例如::

from collections.abc import Callable

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

可以声明可调用的返回类型,而不指定调用签名,方法是用文本省略号替换类型提示中的参数列表: Callable[..., ReturnType] .

将其他可调用函数作为参数的可调用函数可以使用以下命令指示它们的参数类型相互依赖 ParamSpec 。此外,如果该可调用对象向其他可调用对象添加参数或从其他可调用对象中移除参数,则 Concatenate 可以使用运算符。它们采用的形式是 Callable[ParamSpecVariable, ReturnType]Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType] 分别为。

在 3.10 版更改: Callable 现在支持 ParamSpecConcatenate 。看见 PEP 612 了解更多信息。

参见

的文档 ParamSpecConcatenate 提供在中的用法示例 Callable

泛型

由于容器中保存的对象的类型信息不能以一般的方式静态地推断出来,因此抽象基类已经扩展为支持订阅,以表示容器元素的预期类型。

from collections.abc import Mapping, Sequence

def notify_by_email(employees: Sequence[Employee],
                    overrides: Mapping[str, str]) -> None: ...

通过使用一个新的工厂来参数化泛型,该工厂可以在类型中调用 TypeVar .

from collections.abc import Sequence
from typing import TypeVar

T = TypeVar('T')      # Declare type variable

def first(l: Sequence[T]) -> T:   # Generic function
    return l[0]

用户定义的泛型类型

用户定义的类可以定义为泛型类。

from typing import TypeVar, Generic
from logging import Logger

T = TypeVar('T')

class LoggedVar(Generic[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)

Generic[T] 作为一个基类,定义了 LoggedVar 采用单个类型参数 T . 这也使得 T 作为类主体中的类型有效。

这个 Generic 基类定义 __class_getitem__() 以便 LoggedVar[t] 作为类型有效::

from collections.abc import Iterable

def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
    for var in vars:
        var.set(0)

泛型类型可以具有任意数量的类型变量,并且类型变量可以被约束::

from typing import TypeVar, Generic
...

T = TypeVar('T')
S = TypeVar('S', int, str)

class StrangePair(Generic[T, S]):
    ...

每个类型变量的参数 Generic 必须是不同的。因此,这是无效的:

from typing import TypeVar, Generic
...

T = TypeVar('T')

class Pair(Generic[T, T]):   # INVALID
    ...

您可以将多个继承用于 Generic ::

from collections.abc import Sized
from typing import TypeVar, Generic

T = TypeVar('T')

class LinkedList(Sized, Generic[T]):
    ...

从泛型类继承时,某些类型变量可能是固定的::

from collections.abc import Mapping
from typing import TypeVar

T = TypeVar('T')

class MyDict(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
from typing import TypeVar, Union
S = TypeVar('S')
Response = Union[Iterable[S], int]

# Return type here is same as Union[Iterable[str], int]
def response(query: str) -> Response[str]:
    ...

T = TypeVar('T', int, float, complex)
Vec = Iterable[tuple[T, T]]

def inproduct(v: Vec[T]) -> T: # Same as Iterable[tuple[T, T]]
    return sum(x*y for x, y in v)

在 3.7 版更改: Generic 不再有自定义元类。

参数表达式的用户定义泛型也通过以下形式的参数规范变量提供支持 Generic[P] 。该行为与上述类型变量一致,因为类型模块将参数规范变量视为专用类型变量。这方面的一个例外是类型列表可以用来替身一个 ParamSpec ::

>>> from typing import Generic, ParamSpec, TypeVar

>>> T = TypeVar('T')
>>> P = ParamSpec('P')

>>> class Z(Generic[T, P]): ...
...
>>> Z[int, [dict, float]]
__main__.Z[int, (<class 'dict'>, <class 'float'>)]

此外,只有一个参数规范变量的泛型将接受表单中的参数列表 X[[Type1, Type2, ...]] 而且还 X[Type1, Type2, ...] 出于审美原因。在内部,后者转换为前者,因此等价于:

>>> class X(Generic[P]): ...
...
>>> X[int, str]
__main__.X[(<class 'int'>, <class 'str'>)]
>>> X[[int, str]]
__main__.X[(<class 'int'>, <class 'str'>)]

请注意,泛型与 ParamSpec 可能有不正确的地方 __parameters__ 在某些情况下位于替换之后,因为它们主要用于静电类型检查。

在 3.10 版更改: Generic 现在可以在参数表达式上参数化。看见 ParamSpecPEP 612 了解更多详细信息。

用户定义的泛型类可以将abc作为基类,而不存在元类冲突。不支持泛型元类。参数化泛型的结果被缓存,并且类型模块中的大多数类型都是散列的,并且在相等性方面是可比较的。

这个 Any 类型

一种特殊的类型是 Any . 静态类型检查器会将每种类型视为与 AnyAny 与每种类型都兼容。

这意味着可以对类型的值执行任何操作或方法调用 Any 并将其分配给任何变量:

from typing import Any

a = None    # type: Any
a = []      # OK
a = 2       # OK

s = ''      # type: str
s = a       # OK

def foo(item: Any) -> int:
    # Typechecks; 'item' could be any type,
    # and that type might have a 'bar' method
    item.bar()
    ...

请注意,在分配类型的值时不执行类型检查 Any 更精确的类型。例如,静态类型检查器在分配时没有报告错误 as 尽管 s 已声明为类型 str 接收一个 int 运行时的值!

此外,没有返回类型或参数类型的所有函数都将默认为使用 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 ,则相反: objectnot 其他类型的子类型。

这意味着当一个值的类型是 object 类型检查器将拒绝对其执行的几乎所有操作,并将其分配给更专用类型的变量(或将其用作返回值)是一个类型错误。例如::

def hash_a(item: object) -> int:
    # Fails; an object does not have a 'magic' method.
    item.magic()
    ...

def hash_b(item: Any) -> int:
    # Typechecks
    item.magic()
    ...

# Typechecks, since ints and strs are subclasses of object
hash_a(42)
hash_a("foo")

# Typechecks, since Any is compatible with all types
hash_b(42)
hash_b("foo")

使用 object 以类型安全的方式指示值可以是任何类型。使用 Any 指示值是动态类型的。

名义与结构子类型

最初 PEP 484 定义了python静态类型系统 名义子类型 . 这意味着一个班 A 在一个类中允许 B 当且仅当 A 是的子类 B .

这一要求以前也适用于抽象基类,例如 Iterable 。这种方法的问题是必须显式标记一个类才能支持它们,这是非Python式的,并且不像在惯用的动态类型Python代码中通常所做的那样。例如,这符合 PEP 484 ::

from collections.abc import Sized, Iterable, Iterator

class Bucket(Sized, Iterable[int]):
    ...
    def __len__(self) -> int: ...
    def __iter__(self) -> Iterator[int]: ...

PEP 544 允许用户在类定义中不使用显式基类编写上述代码,从而解决此问题,允许 Bucket 隐式地被认为是 SizedIterable[int] 通过静态类型检查程序。这被称为 结构子类型 (或静态duck类型)::

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 用户可以定义新的自定义协议来完全享受结构子类型(参见下面的示例)。

模块内容

该模块定义了以下类、函数和修饰符。

注解

此模块定义了几个类型,这些类型是预先存在的标准库类的子类,这些类也扩展了 Generic 在内部支持类型变量 [] . 在Python3.9中,当相应的预先存在的类得到增强以支持时,这些类型就变得多余了 [] .

从python3.9开始,冗余类型是不推荐使用的,但是解释器不会发出弃用警告。当检查的程序以python3.9或更新版本为目标时,类型检查程序将标记不推荐使用的类型。

不推荐使用的类型将从 typing 在python3.9.0发布5年后发布的第一个Python版本中的模块。有关详细信息,请参阅 PEP 585 - 标准集合中的类型暗示泛型 .

特殊类型原语

特殊类型

它们可以用作批注中的类型,不支持 [] .

typing.Any

表示无约束类型的特殊类型。

  • 每种类型都与 Any .

  • Any 与每种类型都兼容。

typing.NoReturn

表示函数永不返回的特殊类型。例如::

from typing import NoReturn

def stop() -> NoReturn:
    raise RuntimeError('no way')

3.5.4 新版功能.

3.6.2 新版功能.

typing.TypeAlias

用于显式声明 type alias 。例如::

from typing import TypeAlias

Factors: TypeAlias = list[int]

看见 PEP 613 了解有关显式类型别名的更多详细信息。

3.10 新版功能.

特殊形式

这些可以作为注释中的类型使用 [] ,每个都有一个独特的语法。

typing.Tuple

元组类型; Tuple[X, Y] 是由两个项组成的元组的类型,第一个项的类型为X,第二个项的类型为Y。空元组的类型可以写为 Tuple[()] .

例子: Tuple[T1, T2] 是对应于类型变量T1和T2的两个元素的元组。 Tuple[int, float, str] 是int、float和string的元组。

要指定同构类型的可变长度元组,请使用文本省略号,例如。 Tuple[int, ...] .平原 Tuple 等于 Tuple[Any, ...] ,依次为 tuple .

3.9 版后已移除: builtins.tuple 现在支持 [] 。看见 PEP 585通用别名类型

typing.Union

联合类型; Union[X, Y] 表示x或y。

要定义联合,请使用例如 Union[int, str] . 细节:

  • 参数必须是类型,并且必须至少有一个类型。

  • 工会工会被压扁,例如:

    Union[Union[int, str], float] == Union[int, str, float]
    
  • 单一参数的联合消失,例如:

    Union[int] == int  # The constructor actually returns int
    
  • 跳过冗余参数,例如:

    Union[int, str, int] == Union[int, str]
    
  • 比较联合时,参数顺序被忽略,例如:

    Union[int, str] == Union[str, int]
    
  • 不能对联合进行子类化或实例化。

  • 你不能写 Union[X][Y] .

  • 你可以使用 Optional[X] 作为 Union[X, None] .

在 3.7 版更改: 不要在运行时从联合中删除显式子类。

在 3.10 版更改: 联合现在可以写成 X | Y 。看见 union type expressions

typing.Optional

可选类型。

Optional[X] 等于 Union[X, None] .

请注意,这与可选参数的概念不同,后者具有默认值。带有默认值的可选参数不需要 Optional 类型批注上的限定符,因为它是可选的。例如::

def foo(arg: int = 0) -> None:
    ...

另一方面,如果 None 是允许的,使用 Optional 是适当的,无论参数是否可选。例如::

def foo(arg: Optional[int] = None) -> None:
    ...
typing.Callable

可调用类型; Callable[[int], str] 是(int)->str的函数。

订阅语法必须始终与两个值一起使用:参数列表和返回类型。参数列表必须是类型列表或省略号;返回类型必须是单个类型。

没有语法来指示可选参数或关键字参数;此类函数类型很少用作回调类型。 Callable[..., ReturnType] (字面省略号)可用于键入提示可调用,接受任意数量的参数并返回 ReturnType . 平原 Callable 等于 Callable[..., Any] ,依次为 collections.abc.Callable .

将其他可调用函数作为参数的可调用函数可以使用以下命令指示它们的参数类型相互依赖 ParamSpec 。此外,如果该可调用对象向其他可调用对象添加参数或从其他可调用对象中移除参数,则 Concatenate 可以使用运算符。它们采用的形式是 Callable[ParamSpecVariable, ReturnType]Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType] 分别为。

3.9 版后已移除: collections.abc.Callable 现在支持 [] 。看见 PEP 585通用别名类型

在 3.10 版更改: Callable 现在支持 ParamSpecConcatenate 。看见 PEP 612 了解更多信息。

参见

的文档 ParamSpecConcatenate 提供与一起使用的示例 Callable

typing.Concatenate

CallableParamSpec 要对添加、移除或转换另一个可调用对象的参数的高阶可调用对象进行类型注释,请执行以下操作。用法在表单中 Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]Concatenate 当前仅在用作 Callable 。的最后一个参数 Concatenate 必须是 ParamSpec

例如,要注释装饰器,请执行以下操作 with_lock 它提供了一个 threading.Lock 添加到装饰过的函数中, Concatenate 可以用来表示 with_lock 需要一个可调用函数,该函数接受 Lock 作为第一个参数,并返回具有不同类型签名的可调用对象。在本例中, ParamSpec 指示返回的可调用对象的参数类型取决于传入的可调用对象的参数类型::

from collections.abc import Callable
from threading import Lock
from typing import Any, Concatenate, ParamSpec, TypeVar

P = ParamSpec('P')
R = TypeVar('R')

# Use this lock to ensure that only one thread is executing a function
# at any time.
my_lock = Lock()

def with_lock(f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]:
    '''A type-safe decorator which provides a lock.'''
    global my_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 新版功能.

参见

class typing.Type(Generic[CT_co])

用注释的变量 C 可以接受类型的值 C . 相反,一个变量 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 BasicUser(User): ...
class ProUser(User): ...
class TeamUser(User): ...

# Accepts User, BasicUser, ProUser, TeamUser, ...
def make_new_user(user_class: Type[User]) -> User:
    # ...
    return user_class()

事实是 Type[C] 协变意味着 C 应实现与相同的构造函数签名和类方法签名 C . 类型检查程序应标记违反此规则的情况,但也应允许子类中与指定的基类中的构造函数调用匹配的构造函数调用。在以后的版本中,类型检查程序如何处理这种特殊情况可能会发生变化。 PEP 484 .

唯一合法参数 Type 是类, Anytype variables 以及这些类型的联合。例如::

def new_non_team_user(user_class: Type[Union[BasicUser, ProUser]]): ...

Type[Any] 等于 Type 反过来相当于 type ,它是Python元类层次结构的根。

3.5.2 新版功能.

3.9 版后已移除: builtins.type 现在支持 [] 。看见 PEP 585通用别名类型

typing.Literal

一种类型,可用于向类型检查程序指示相应的变量或函数参数具有与所提供的文本(或多个文本之一)等效的值。例如::

def validate_simple(data: Any) -> Literal[True]:  # always returns True
    ...

MODE = Literal['r', 'rb', 'w', 'wb']
def open_helper(file: str, mode: MODE) -> str:
    ...

open_helper('/some/path', 'r')  # Passes type check
open_helper('/other/path', 'typo')  # Error in type checker

Literal[...] 不能子类化。在运行时,允许将任意值作为 Literal[...] 但类型检查程序可能会施加限制。见 PEP 586 有关文本类型的详细信息。

3.8 新版功能.

在 3.9.1 版更改: Literal 现在对参数执行重复数据消除。平等比较 Literal 对象不再依赖于顺序。 Literal 对象现在将引发 TypeError 如果它们的一个参数不是 immutable

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.Annotated

A type, introduced in PEP 593 (Flexible function and variable annotations), to decorate existing types with context-specific metadata (possibly multiple pieces of it, as Annotated is variadic). Specifically, a type T can be annotated with metadata x via the typehint Annotated[T, x]. This metadata can be used for either static analysis or at runtime. If a library (or tool) encounters a typehint Annotated[T, x] and has no special logic for metadata x, it should ignore it and simply treat the type as T. Unlike the no_type_check functionality that currently exists in the typing module which completely disables typechecking annotations on a function or a class, the Annotated type allows for both static typechecking of T (e.g., via mypy or Pyre, which can safely ignore x) together with runtime access to x within a specific application.

最终,如何解释注释(如果有的话)的责任是遇到 Annotated 键入。遇到 Annotated 类型可以扫描注释以确定是否感兴趣(例如,使用 isinstance()

当工具或库不支持批注或遇到未知批注时,应忽略它,并将带批注的类型视为基础类型。

由使用注释的工具来决定是否允许客户端在一个类型上有多个注释,以及如何合并这些注释。

自从 Annotated 类型允许您在任何节点上放置多个相同(或不同)类型的批注,使用这些批注的工具或库负责处理潜在的重复项。例如,如果您正在进行值范围分析,则可能允许这样做:

T1 = Annotated[int, ValueRange(-10, 5)]
T2 = Annotated[T1, ValueRange(-20, 3)]

经过 include_extras=Trueget_type_hints() 允许在运行时访问额外的注释。

语法细节:

  • 第一个论点 Annotated 必须是有效类型

  • 支持多种类型批注 (Annotated 支持可变参数)::

    Annotated[int, ValueRange(3, 10), ctype("char")]
    
  • Annotated 必须使用至少两个参数调用( Annotated[int] 无效)

  • 注释的顺序被保留,对于相等性检查很重要:

    Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[
        int, ctype("char"), ValueRange(3, 10)
    ]
    
  • 嵌套的 Annotated 类型被展平,元数据以最里面的注释开始排序:

    Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[
        int, ValueRange(3, 10), ctype("char")
    ]
    
  • 不会删除重复的批注:

    Annotated[int, ValueRange(3, 10)] != Annotated[
        int, ValueRange(3, 10), ValueRange(3, 10)
    ]
    
  • Annotated 可与嵌套别名和泛型别名一起使用:

    T = TypeVar('T')
    Vec = Annotated[list[tuple[T, T]], MaxLen(10)]
    V = Vec[int]
    
    V == Annotated[list[tuple[int, int]], MaxLen(10)]
    

3.9 新版功能.

生成泛型类型

它们不用于注释。它们是创建泛型类型的构建块。

class typing.Generic

泛型类型的抽象基类。

泛型类型通常通过使用一个或多个类型变量从此类的实例化继承来声明。例如,通用映射类型可以定义为::

class Mapping(Generic[KT, VT]):
    def __getitem__(self, key: KT) -> VT:
        ...
        # Etc.

然后可以按如下方式使用此类:

X = TypeVar('X')
Y = TypeVar('Y')

def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y:
    try:
        return mapping[key]
    except KeyError:
        return default
class typing.TypeVar

类型变量。

用法:

T = TypeVar('T')  # Can be anything
A = TypeVar('A', str, bytes)  # Must be str or bytes

类型变量的存在主要是为了让静态类型检查程序受益。它们充当泛型类型和泛型函数定义的参数。看到了吗 Generic 有关泛型类型的详细信息。通用函数的工作方式如下:

def repeat(x: T, n: int) -> Sequence[T]:
    """Return a list containing n references to x."""
    return [x]*n

def longest(x: A, y: A) -> A:
    """Return the longest of two strings."""
    return x if len(x) >= len(y) else y

后一个示例的签名本质上是 (str, str) -> str(bytes, bytes) -> bytes . 还要注意,如果参数是 str ,返回类型仍然是普通的 str .

在运行时, isinstance(x, T) 将提高 TypeError . 一般来说, isinstance()issubclass()

类型变量可以通过传递标记为协变或逆变 covariant=Truecontravariant=True . 见 PEP 484 了解更多详细信息。默认情况下,类型变量是不变的。或者,类型变量可以使用 bound=<type> . 这意味着类型变量的实际类型(显式或隐式)必须是边界类型的子类,请参见 PEP 484 .

class typing.ParamSpec(name, *, bound=None, covariant=False, contravariant=False)

参数规范变量。专门化版本的 type variables

用法:

P = ParamSpec('P')

存在参数规范变量主要是为了便于静电类型检查器使用。它们用于将一个可调用函数的参数类型转发给另一个可调用函数--这是高阶函数和修饰符中常见的模式。它们只有在以下情况下使用时才有效 Concatenate ,或者作为的第一个参数 Callable ,或作为用户定义泛型的参数。看见 Generic 有关泛型类型的更多信息,请参见。

例如,要向函数添加基本日志记录,可以创建一个修饰符 add_logging 若要记录函数调用,请执行以下操作。参数规范变量告诉类型检查器传递给修饰符的可调用对象和它返回的新可调用对象具有相互依赖的类型参数:

from collections.abc import Callable
from typing import TypeVar, ParamSpec
import logging

T = TypeVar('T')
P = ParamSpec('P')

def add_logging(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 ,以前注释这一点的最简单方法是使用 TypeVar 使用绑定 Callable[..., Any] 。但是,这会导致两个问题:

  1. 类型检查器无法类型检查 inner 函数,因为 *args**kwargs 必须打字 Any

  2. cast() 的正文中可能需要 add_logging 装饰者在返回 inner 函数,否则必须告诉静电类型检查器忽略 return inner

args
kwargs

因为 ParamSpec 捕获位置参数和关键字参数, P.argsP.kwargs 可用于拆分 ParamSpec 放入它的组件中。 P.args 表示给定调用中的位置参数元组,应仅用于批注 *argsP.kwargs 表示给定调用中关键字参数到其值的映射,应仅用于批注 **kwargs**kwds 。这两个属性都要求带注释的参数在作用域内。

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

3.10 新版功能.

注解

只能对全局作用域中定义的参数规范变量进行酸洗。

参见

typing.AnyStr

AnyStr 类型变量定义为 AnyStr = TypeVar('AnyStr', str, bytes) .

它用于可以接受任何类型字符串而不允许不同类型字符串混合的函数。例如::

def concat(a: AnyStr, b: AnyStr) -> AnyStr:
    return a + b

concat(u"foo", u"bar")  # Ok, output has type 'unicode'
concat(b"foo", b"bar")  # Ok, output has type 'bytes'
concat(u"foo", b"bar")  # Error, cannot mix unicode and bytes
class typing.Protocol(Generic)

协议类的基类。协议类的定义如下:

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

此类类主要用于识别结构子类型(静态duck类型)的静态类型检查程序,例如:

class C:
    def meth(self) -> int:
        return 0

def func(x: Proto) -> int:
    return x.meth()

func(C())  # Passes static type check

PEP 544 有关详细信息。协议类装饰有 runtime_checkable() (稍后描述)作为简单的运行时协议,只检查给定属性的存在,忽略它们的类型签名。

协议类可以是通用的,例如:

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

3.8 新版功能.

@typing.runtime_checkable

将协议类标记为运行时协议。

这样的协议可以与 isinstance()issubclass() . 这提出 TypeError 当应用于非协议类时。这使得一个简单的结构检查,非常类似于“一个技巧小马” collections.abcIterable . 例如::

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

assert isinstance(open('/some/file'), Closable)

注解

runtime_checkable() 将只检查所需方法的存在,而不是其类型签名!例如, builtins.complex 器具 __float__() ,因此它通过一个 issubclass() 对照 SupportsFloat . 然而, complex.__float__ 方法的存在只是为了引发 TypeError 一条信息更丰富的信息。

3.8 新版功能.

其他特殊指令

它们不用于注释。它们是声明类型的构造块。

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__ 给出将字段名映射到字段类型的dict。(字段名位于 _fields 属性和默认值位于 _field_defaults 属性,这两个属性都是NamedDuple API的一部分。)

NamedTuple 子类也可以有docstring和方法:

class Employee(NamedTuple):
    """Represents an employee."""
    name: str
    id: int = 3

    def __repr__(self) -> str:
        return f'<Employee {self.name}, id={self.id}>'

向后兼容用法:

Employee = NamedTuple('Employee', [('name', str), ('id', int)])

在 3.6 版更改: 为添加了支持 PEP 526 变量注释语法。

在 3.6.1 版更改: 增加了对默认值、方法和docstring的支持。

在 3.8 版更改: 这个 _field_types__annotations__ 属性现在是常规字典,而不是 OrderedDict .

在 3.9 版更改: 移除 _field_types 倾向于更标准的属性 __annotations__ 具有相同信息的属性。

typing.NewType(name, tp)

用于向类型检查器指示不同类型的帮助函数,请参见 NewType . 在运行时,它返回一个返回其参数的函数。用法:

UserId = NewType('UserId', int)
first_user = UserId(1)

3.5.2 新版功能.

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')

可通过以下方式访问自省的类型信息: Point2D.__annotations__Point2D.__total__ . 允许将此功能与不支持的旧版本的python一起使用 PEP 526TypedDict 支持两种附加的等效句法形式:

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

默认情况下,所有键都必须出现在TypedDict中。可以通过指定totality来覆盖这一点。用法:

class point2D(TypedDict, total=False):
    x: int
    y: int

这意味着point2D TypedDict可以省略任何键。类型检查器只应支持将文本False或True作为total参数的值。True是默认值,它使类主体中定义的所有项都成为必需项。

PEP 589 有关更多示例和详细的使用规则 TypedDict .

3.8 新版功能.

普通混凝土集合

对应内置类型

class typing.Dict(dict, MutableMapping[KT, VT])

的通用版本 dict . 用于注释返回类型。要注释参数,最好使用抽象集合类型,例如 Mapping .

此类型可以如下使用:

def count_words(text: str) -> Dict[str, int]:
    ...

3.9 版后已移除: builtins.dict 现在支持 [] 。看见 PEP 585通用别名类型

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

的通用版本 list . 用于注释返回类型。要注释参数,最好使用抽象集合类型,例如 SequenceIterable .

此类型可以如下使用:

T = TypeVar('T', int, float)

def vec2(x: T, y: T) -> List[T]:
    return [x, y]

def keep_positives(vector: Sequence[T]) -> List[T]:
    return [item for item in vector if item > 0]

3.9 版后已移除: builtins.list 现在支持 [] 。看见 PEP 585通用别名类型

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

的通用版本 builtins.set . 用于注释返回类型。要注释参数,最好使用抽象集合类型,例如 AbstractSet .

3.9 版后已移除: builtins.set 现在支持 [] 。看见 PEP 585通用别名类型

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

的通用版本 builtins.frozenset .

3.9 版后已移除: builtins.frozenset 现在支持 [] 。看见 PEP 585通用别名类型

注解

Tuple 是一种特殊的形式。

对应于中的类型 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.5.4 新版功能.

3.6.1 新版功能.

3.9 版后已移除: collections.ChainMap 现在支持 [] 。看见 PEP 585通用别名类型

class typing.Counter(collections.Counter, Dict[T, int])

的通用版本 collections.Counter .

3.5.4 新版功能.

3.6.1 新版功能.

3.9 版后已移除: collections.Counter 现在支持 [] 。看见 PEP 585通用别名类型

class typing.Deque(deque, MutableSequence[T])

的通用版本 collections.deque .

3.5.4 新版功能.

3.6.1 新版功能.

3.9 版后已移除: collections.deque 现在支持 [] 。看见 PEP 585通用别名类型

其他混凝土类型

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

泛型类型 IO[AnyStr] 及其子类 TextIO(IO[str])BinaryIO(IO[bytes]) 表示I/O流的类型,如 open() . 这些类型也在 typing.io 命名空间。

class typing.Pattern
class typing.Match

这些类型别名对应于 re.compile()re.match() . 这些类型(以及相应的函数)在 AnyStr 并且可以通过书面形式具体说明 Pattern[str]Pattern[bytes]Match[str]Match[bytes] . 这些类型也在 typing.re 命名空间。

3.9 版后已移除: 班级 PatternMatch 从… re 现在支持 [] 。看见 PEP 585通用别名类型

class typing.Text

Text 是一个别名 str . 它为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 新版功能.

抽象基类

对应于中的集合 collections.abc

class typing.AbstractSet(Sized, Collection[T_co])

的通用版本 collections.abc.Set .

3.9 版后已移除: collections.abc.Set 现在支持 [] 。看见 PEP 585通用别名类型

class typing.ByteString(Sequence[int])

的通用版本 collections.abc.ByteString .

此类型表示类型 bytesbytearraymemoryview 字节序列。

作为这种类型的简写, bytes 可用于注释上述任何类型的参数。

3.9 版后已移除: collections.abc.ByteString 现在支持 [] 。看见 PEP 585通用别名类型

class typing.Collection(Sized, Iterable[T_co], Container[T_co])

的通用版本 collections.abc.Collection

3.6.0 新版功能.

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, Generic[KT_co, VT_co])

的通用版本 collections.abc.ItemsView .

3.9 版后已移除: collections.abc.ItemsView 现在支持 [] 。看见 PEP 585通用别名类型

class typing.KeysView(MappingView[KT_co], AbstractSet[KT_co])

的通用版本 collections.abc.KeysView .

3.9 版后已移除: collections.abc.KeysView 现在支持 [] 。看见 PEP 585通用别名类型

class typing.Mapping(Sized, Collection[KT], Generic[VT_co])

的通用版本 collections.abc.Mapping . 此类型可以如下使用:

def get_position_in_index(word_list: Mapping[str, int], word: str) -> int:
    return word_list[word]

3.9 版后已移除: collections.abc.Mapping 现在支持 [] 。看见 PEP 585通用别名类型

class typing.MappingView(Sized, Iterable[T_co])

的通用版本 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[VT_co])

的通用版本 collections.abc.ValuesView .

3.9 版后已移除: collections.abc.ValuesView 现在支持 [] 。看见 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通用别名类型

class typing.Generator(Iterator[T_co], Generic[T_co, T_contra, V_co])

生成器可以由泛型类型进行注释。 Generator[YieldType, SendType, ReturnType] . 例如::

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

注意,与类型模块中的许多其他泛型不同, SendType 属于 Generator 行为是相反的,不是协变的或不变的。

如果生成器只生成值,请设置 SendTypeReturnTypeNone ::

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

3.9 版后已移除: collections.abc.Generator 现在支持 [] 。看见 PEP 585通用别名类型

class typing.Hashable

的别名 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

异步编程

class typing.Coroutine(Awaitable[V_co], Generic[T_co, T_contra, V_co])

的通用版本 collections.abc.Coroutine . 类型变量的方差和顺序与 Generator 例如:

from collections.abc import Coroutine
c = None # type: Coroutine[list[str], str, int]
...
x = c.send('hi') # type: list[str]
async def bar() -> None:
    x = await c # type: int

3.5.3 新版功能.

3.9 版后已移除: collections.abc.Coroutine 现在支持 [] 。看见 PEP 585通用别名类型

class typing.AsyncGenerator(AsyncIterator[T_co], Generic[T_co, T_contra])

异步生成器可以由泛型类型注释 AsyncGenerator[YieldType, SendType] . 例如::

async def echo_round() -> AsyncGenerator[int, float]:
    sent = yield 0
    while sent >= 0.0:
        rounded = await round(sent)
        sent = yield rounded

与普通生成器不同,异步生成器不能返回值,因此没有 ReturnType 类型参数。和一样 Generator , the SendType 行为相反。

如果生成器只生成值,请设置 SendTypeNone ::

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)

3.6.1 新版功能.

3.9 版后已移除: collections.abc.AsyncGenerator 现在支持 [] 。看见 PEP 585通用别名类型

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通用别名类型

上下文管理器类型

class typing.ContextManager(Generic[T_co])

的通用版本 contextlib.AbstractContextManager .

3.5.4 新版功能.

3.6.0 新版功能.

3.9 版后已移除: contextlib.AbstractContextManager 现在支持 [] 。看见 PEP 585通用别名类型

class typing.AsyncContextManager(Generic[T_co])

的通用版本 contextlib.AbstractAsyncContextManager .

3.5.4 新版功能.

3.6.2 新版功能.

3.9 版后已移除: contextlib.AbstractAsyncContextManager 现在支持 [] 。看见 PEP 585通用别名类型

协议

这些协议用 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__ 它的返回类型是协变的。

功能和装饰器

typing.cast(typ, val)

将值强制转换为类型。

这将返回值不变。对于类型检查器,这表示返回值具有指定的类型,但在运行时,我们故意不检查任何内容(我们希望尽可能快地检查)。

@typing.overload

这个 @overload decorator允许描述支持多种不同参数类型组合的函数和方法。一系列 @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>

PEP 484 以获取详细信息并与其他类型语义进行比较。

@typing.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 新版功能.

@typing.no_type_check

指示注释不是类型提示的decorator。

它作为类或函数工作 decorator .对于一个类,它递归地应用于该类中定义的所有方法(但不应用于在其超类或子类中定义的方法)。

这会使功能发生变化。

@typing.no_type_check_decorator

装饰师给另一个装饰师 no_type_check() 效果。

它用一些东西把装饰的功能包起来 no_type_check() .

@typing.type_check_only

Decorator 将类或函数标记为在运行时不可用。

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

@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__ . 此外,通过在 globalslocals 命名空间。如有必要, Optional[t] 如果默认值等于 None 被设置。为类 C ,返回通过合并所有 __annotations__ 沿着 C.__mro__ 以相反的顺序。

函数递归地替换所有 Annotated[T, ...] 具有 T 除非 include_extras 设置为 True (见 Annotated 更多信息)。例如::

class Student(NamedTuple):
    name: Annotated[str, 'some marker']

get_type_hints(Student) == {'name': str}
get_type_hints(Student, include_extras=False) == {'name': str}
get_type_hints(Student, include_extras=True) == {
    'name': Annotated[str, 'some marker']
}

在 3.9 版更改: 补充 include_extras 参数作为 PEP 593 .

typing.get_args(tp)
typing.get_origin(tp)

为一般类型和特殊类型表单提供基本的内省。

对于表单的键入对象, X[Y, Z, ...] 这些函数返回 X(Y, Z, ...) 。如果 X 是内置或 collections 类,它将被规范化为原始类。如果 X 是一种 UnionLiteral 包含在另一个泛型类型中,顺序为 (Y, Z, ...) 可能与原始参数的顺序不同 [Y, Z, ...] 由于类型缓存的原因。对于不支持的对象,返回 None() 与之相对应的是。示例:

assert get_origin(Dict[str, int]) is dict
assert get_args(Dict[int, str]) == (int, str)

assert get_origin(Union[int, str]) is Union
assert get_args(Union[int, str]) == (int, str)

3.8 新版功能.

typing.is_typeddict(tp)

检查类型是否为 TypedDict .

例如::

class Film(TypedDict):
    title: str
    year: int

is_typeddict(Film)  # => True
is_typeddict(Union[list, str])  # => False

3.10 新版功能.

class typing.ForwardRef

用于字符串正向引用的内部类型表示的类。例如, list["SomeClass"] 隐式转换为 list[ForwardRef("SomeClass")] 。此类不应由用户实例化,但可以由自检工具使用。

常数

typing.TYPE_CHECKING

假定为 True 由第三方静态类型检查程序执行。它是 False 在运行时。用法:

if TYPE_CHECKING:
    import expensive_mod

def fun(arg: 'expensive_mod.SomeType') -> None:
    local_var: expensive_mod.AnotherType = other_fun()

第一个类型注释必须用引号括起来,使其成为“转发引用”,以隐藏 expensive_mod 来自解释器运行时的引用。不计算局部变量的类型批注,因此不需要将第二个批注括在引号中。

注解

如果 from __future__ import annotations 在Python 3.7或更高版本中使用,则在函数定义时不计算注释。相反,它们作为字符串存储在 __annotations__ ,这使得没有必要在批注两边使用引号。(请参阅 PEP 563 )。

3.5.2 新版功能.