"typing" --- 类型提示支持
*************************

3.5 新版功能.

**源码：** Lib/typing.py

注解:

  Python 运行时不强制执行函数和变量类型注解，但这些注解可用于类型检查
  器、IDE、静态检查器等第三方工具。

======================================================================

本模块为 **PEP 484** 、**PEP 526** 、**PEP 544** 、**PEP 586** 、**PEP
589** 和 **PEP 591** 中的类型提示提供运行时支持。"Any"、"Union"、
"Tuple"、"Callable"、"TypeVar" 和 "Generic" 等类型是最基础的组件。完整
说明详见 **PEP 484**，类型提示简介请参阅 **PEP 483**。

下面的函数接收与返回的都是字符串，注解方式如下：

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

"greeting" 函数中，参数 "name" 的类型是 "str"，返回类型也是 "str"。子
类型也可以当作参数。


类型别名
========

把类型赋给别名，就可以定义类型别名。本例中，"Vector" 和 "list[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()" 辅助函数可创建不同的新类型：

   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)

"UserId" 类型的变量可执行所有 "int" 操作，但返回结果都是 "int" 类型。
这种方式允许在预期 "int" 时传入 "UserId"，还能防止意外创建无效的
"UserId"：

   # 'output' is of type 'int', not 'UserId'
   output = UserId(23413) + UserId(54341)

注意，只有静态类型检查器强制执行这些检查。在运行时，"Derived =
NewType('Derived', Base)" 语句把 "Derived" 当作函数，该函数直接返回传
递给它的任何参数。即，"Derived(some_value)" 表达式不创建新类，或引入超
出调用常规函数的开销。

更确切地说，在运行时，"some_value is Derived(some_value)" 表达式总为
True。

也就是说，不能创建 "Derived" 的子类型，因为，在运行时，它是标识函数，
不是真正的类型：

   from typing import NewType

   UserId = NewType('UserId', int)

   # Fails at runtime and does not 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" 声明把一种类型当作另一种类型的
  *子类型*。"Derived = NewType('Derived', Original)" 时，静态类型检查
  器把 "Derived" 当作 "Original" 的 *子类* ，即，"Original" 类型的值不
  能用在预期 "Derived" 类型的位置。这种方式适用于以最小运行时成本防止
  逻辑错误。

3.5.2 新版功能.


可调对象（Callable）
====================

预期特定签名回调函数的框架可以用 "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]"，就可以声明可调对象的返回类型。


泛型（Generic）
===============

容器中，对象的类型信息不能以泛型方式静态推断，因此，抽象基类扩展支持下
标，用于表示容器元素的预期类型。

   from collections.abc import Mapping, Sequence

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

typing 模块中新推出的 "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" 不再支持自定义元类。

抽象基类可作为用户定义的泛型类的基类，且不会与元类冲突。现已不再支持泛
型元类。参数化泛型的输出结果会被缓存，typing 模块的大多数类型都可哈希
、可进行等价对比。


"Any" 类型
==========

"Any" 是一种特殊的类型。静态类型检查器认为所有类型均与 "Any" 兼容，同
样，"Any" 也与所有类型兼容。

也就是说，可对 "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" 类型的值赋给更精确的类型时，不执行类型检查。例如，把 "a"
赋给 "s"，在运行时，即便 "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" 不同，object 不可逆："object" *不是* 其它类型的子类
型。

就是说，值的类型是 "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"，说明
值是动态类型。


名义子类型 vs 结构子类型
========================

**PEP 484** 最初只是把 Python 静态类型系统定义为应用 *名义子类型*。即
，当且仅当 "A" 是 "B" 的子类时，才能在预期 "B" 类时应用 "A" 类。

此项要求以前也适用于抽象基类，例如，"Iterable" 。这种方式的问题在于，
定义类时必须显式说明，既不 Pythonic，也不是动态类型式 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" ，用户可以定义新
的自定义协议（见下文中的例子）。


模块内容
========

本模块定义了下列类、函数和修饰器。

注解:

  本模块定义了一些类型，作为标准库中已有的类的子类，从而可以让
  "Generic" 支持 "[]" 中的类型变量。Python 3.9 中，这些标准库的类已支
  持 "[]" ，因此，这些类型就变得冗余了。Python 3.9 弃用了这些冗余类型
  ，但解释器并未提供相应的弃用警告。标记弃用类型的工作留待支持 Python
  3.9 及以上版本的类型检查器实现。Python 3.9.0 发布五年后的首个 Python
  发行版将从 "typing" 模块中移除这些弃用类型。详见 **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.Tuple

   元组类型； "Tuple[X, Y]" 是二项元组类型，第一个元素的类型是 X，第二
   个元素的类型是 Y。空元组的类型可写为 "Tuple[()]"。

   例："Tuple[T1, T2]" 是二项元组，类型变量分别为 T1 和 T2。
   "Tuple[int, float, str]" 是由整数、浮点数、字符串组成的三项元组。

   可用省略号字面量指定同质变长元组，例如，"Tuple[int, ...]" 。"Tuple"
   与 "Tuple[Any, ...]" 等价，也与 "tuple" 等价。

   3.9 版后已移除: "builtins.tuple" 现已支持 "[]"。详见 **PEP 585** 与
   Generic Alias Type。

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 版更改: 在运行时，不要移除联合类型中的显式子类。

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" 。

   3.9 版后已移除: "collections.abc.Callable" 现已支持 "[]"。 详见
   **PEP 585** 与 Generic Alias Type。

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" 合法的参数仅有类、"Any" 、类型变量 以及上述类型的联合类型。
   例如：

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

    "Type[Any]" 等价于 "Type"，进而等价于 Python 元类架构的根基，
   "type"。

   3.5.2 新版功能.

   3.9 版后已移除: "builtins.type" 现已支持 "[]"。详见 **PEP 585** 与
   Generic Alias Type。

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" 对象的
   相等性比较不再依赖顺序。 现在如果有某个参数不为 *hashable*，
   "Literal" 对象在相等性比较期间将引发 "TypeError"。

typing.ClassVar

   标记类变量的特殊类型构造器。

   如 **PEP 526** 所述，打包在 ClassVar 内的变量注解是指，给定属性应当
   用作类变量，而不应设置在类实例上。用法如下：

      class Starship:
          stats: ClassVar[dict[str, int]] = {} # class variable
          damage: int = 10                     # instance variable

   "ClassVar" 仅接受类型，也不能使用下标。

   "ClassVar" 本身不是类，不应用于 "isinstance()" 或 "issubclass()"。
   "ClassVar" 不改变 Python 运行时行为，但可以用于第三方类型检查器。例
   如，类型检查器会认为以下代码有错：

      enterprise_d = Starship(3000)
      enterprise_d.stats = {} # Error, setting class variable on instance
      Starship.stats = {}     # This is OK

   3.5.3 新版功能.

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

   **PEP 593** （"灵活函数和变量注解"）里引入的类型，可以用上下文特定
   元数据（"Annotated" 的参数可变，也可能用它的多个组成部分）装饰现有
   的类型。具体来说，就是类型提示 "Annotated[T, x]" 用元数据 "x" 注解
   类型 "T"。静态分析或运行时都能使用该元数据。库（或工具）处理类型提
   示 "Annotated[T, x]" 时，在元数据 "x" 不涉及特殊逻辑的情况下，可忽
   略该类型提示，仅把它当作类型 "T"。与 "typing" 模块中现有的
   "no_type_check" 功能不同，该功能完全禁用了函数或类的类型检查注解，
   而 "Annotated" 类型则允许对 "T" 进行静态类型检查（例如，通过 mypy
   或 Pyre，可安全地忽略 "x"），也可以在特定应用程序中实现 "x" 的运行
   时访问。

   毕竟，如何解释注解（如有）由处理 "Annotated" 类型的工具/库负责。工
   具/库处理 "Annotated" 类型时，扫描所有注解以确定是否需要进行处理（
   例如，使用 "isinstance()"）。

   工具/库不支持注解，或遇到未知注解时，应忽略注解，并把注解类型当作底
   层类型。

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

   "Annotated" 类型支持把多个相同（或不同）的单个（或多个）类型注解置
   于任意节点。因此，使用这些注解的工具/库要负责处理潜在的重复项。例如
   ，执行值范围分析时，应允许以下操作：

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

   传递 "include_extras=True" 至 "get_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=True" 或 "contravariant=True" 可以把类型变量标记为
   协变量或逆变量。详见 **PEP 484**。默认情况下，类型变量是不变量。类
   型变量还可以用 "bound=<type>" 指定上限。这里的意思是，（显式或隐式
   地）取代类型变量的实际类型必须是限定类型的子类，详见 **PEP 484**。

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)

   Protocol 类的基类。Protocol 类的定义如下：

      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**。Protocol 类用 "runtime_checkable()" （见下文）装
   饰，忽略类型签名，仅检查给定属性是否存在，充当简要的运行时协议。

   Protocol 类可以是泛型，例如：

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

   3.8 新版功能.

@typing.runtime_checkable

   用于把 Protocol 类标记为运行时协议。

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

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

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

   注解:

     "runtime_checkable()" 只检查所需方法是否存在，但却不检查类型签名
     ！ 例如，"builtins.complex" 支持 "__float__()"，因此，它能通过
     "SupportsFloat"  的 "issubclass()" 检查。 然而，
     "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__" 这个附加属性，提供了映射字段名与字段
   类型的字典。（字段名在 "_fields" 属性内，默认值在 "_field_defaults"
   属性内，这两项都是命名元组 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}>'

   反向兼容用法：

      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__" 属性。

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__" 访问。为了让不支持 **PEP 526** 的老版 Python 也
   能使用此功能，"TypedDict" 支持两个附加的等价句法形式：

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

   默认情况下，所有键都必须列在 TypedDict 里。不过，也可以通过指定
   total 参数进行重写。用法如下：

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

   这段代码的意思是，可以省略 point2D 这个 TypedDict 中的任意键。类型
   检查器只支持字面量 False 或 True 作为 total 参数的值。True 是默认值
   ，表明在类体中，必须定义所有项目。

   更多示例与 "TypedDict" 的详细规则，详见 **PEP 589**。

   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** 和
   Generic Alias Type。

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

   "list" 的泛型版本。适用于注解返回类型。注解参数时，最好使用
   "Sequence" 或 "Iterable" 等抽象容器类型。

   该类型用法如下：

      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** 与
   Generic Alias Type。

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

   "builtins.set" 的泛型版本。适用于注解返回类型。注解参数时，最好使用
   "AbstractSet" 等抽象容器类型。

   3.9 版后已移除: "builtins.set" 现已支持 "[]"。详见 **PEP 585** 和
   Generic Alias Type。

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

   "builtins.frozenset" 的泛型版本。

   3.9 版后已移除: "builtins.frozenset" 现已支持 "[]"。详见 **PEP
   585** 和 Generic Alias Type。

注解:

  "Tuple" 是一种特殊形式。


"collections" 对应类型
~~~~~~~~~~~~~~~~~~~~~~

class typing.DefaultDict(collections.defaultdict, MutableMapping[KT, VT])

   "collections.defaultdict" 的泛型版本。

   3.5.2 新版功能.

   3.9 版后已移除: "collections.defaultdict" 现已支持 "[]"。详见 **PEP
   585** 与 Generic Alias Type。

class typing.OrderedDict(collections.OrderedDict, MutableMapping[KT, VT])

   "collections.OrderedDict" 的泛型版本。

   3.7.2 新版功能.

   3.9 版后已移除: "collections.OrderedDict" 现已支持 "[]"。详见 **PEP
   585** 与 Generic Alias Type。

class typing.ChainMap(collections.ChainMap, MutableMapping[KT, VT])

   "collections.ChainMap" 的泛型版本。

   3.5.4 新版功能.

   3.6.1 新版功能.

   3.9 版后已移除: "collections.ChainMap" 现已支持 "[]"。详见 **PEP
   585** 和 Generic Alias Type。

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

   "collections.Counter" 的泛型版本。

   3.5.4 新版功能.

   3.6.1 新版功能.

   3.9 版后已移除: "collections.Counter" 现已支持 "[]"。详见 **PEP
   585** 和 Generic Alias Type。

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

   "collections.deque" 的泛型版本。

   3.5.4 新版功能.

   3.6.1 新版功能.

   3.9 版后已移除: "collections.deque" 现已支持 "[]"。详见 **PEP 585**
   和 Generic Alias Type。


其他具象类型
~~~~~~~~~~~~

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

   泛型类型 "IO[AnyStr]" 及其子类 "TextIO(IO[str])" 与
   "BinaryIO(IO[bytes])" 表示 I/O 流的类型，例如 "open()" 所返回的对象
   。

   Deprecated since version 3.8, will be removed in version 3.12: 这些
   类型也在 "typing.io" 命名空间中，它从未得到类型检查器的支持并将被移
   除。

class typing.Pattern
class typing.Match

   这些类型对应的是从 "re.compile()" 和 "re.match()" 返回的类型。 这些
   类型（及相应的函数）是 "AnyStr" 中的泛型并可通过编写
   "Pattern[str]", "Pattern[bytes]", "Match[str]" 或 "Match[bytes]" 来
   具体指定。

   Deprecated since version 3.8, will be removed in version 3.12: 这些
   类型也在 "typing.re" 命名空间中，它从未得到类型检查器的支持并将被移
   除。

   3.9 版后已移除: "re" 模块中的 "Pattern" 与 "Match" 类现已支持 "[]"
   。详见 **PEP 585** 与 Generic Alias Type。

class typing.Text

   "Text" 是 "str" 的别名。提供了对 Python 2 代码的向下兼容：Python 2
   中，"Text" 是 "unicode" 的别名。

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

      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** 与 Generic Alias Type。

class typing.ByteString(Sequence[int])

   "collections.abc.ByteString" 的泛型版本。

   该类型代表了 "bytes"、"bytearray"、"memoryview" 等字节序列类型。

   作为该类型的简称，"bytes" 可用于标注上述任意类型的参数。

   3.9 版后已移除: "collections.abc.ByteString" 现已支持 "[]"。详见
   **PEP 585** 与 Generic Alias Type。

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

   "collections.abc.Collection" 的泛型版本。

   3.6.0 新版功能.

   3.9 版后已移除: "collections.abc.Collection" 现已支持 "[]"。详见
   **PEP 585** 与 Generic Alias Type。

class typing.Container(Generic[T_co])

   "collections.abc.Container" 的泛型版本。

   3.9 版后已移除: "collections.abc.Container" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

class typing.ItemsView(MappingView, Generic[KT_co, VT_co])

   "collections.abc.ItemsView" 的泛型版本。

   3.9 版后已移除: "collections.abc.ItemsView" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

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

   "collections.abc.KeysView" 的泛型版本。

   3.9 版后已移除: "collections.abc.KeysView" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

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** 和 Generic Alias Type。

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

   "collections.abc.MappingView" 的泛型版本。

   3.9 版后已移除: "collections.abc.MappingView" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

class typing.MutableMapping(Mapping[KT, VT])

   "collections.abc.MutableMapping" 的泛型版本。

   3.9 版后已移除: "collections.abc.MutableMapping" 现已支持 "[]"。详
   见 **PEP 585** 和 Generic Alias Type。

class typing.MutableSequence(Sequence[T])

   "collections.abc.MutableSequence" 的泛型版本。

   3.9 版后已移除: "collections.abc.MutableSequence" 现已支持 "[]"。详
   见 **PEP 585** 和 Generic Alias Type。

class typing.MutableSet(AbstractSet[T])

   "collections.abc.MutableSet" 的泛型版本。

   3.9 版后已移除: "collections.abc.MutableSet" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

class typing.Sequence(Reversible[T_co], Collection[T_co])

   "collections.abc.Sequence" 的泛型版本。

   3.9 版后已移除: "collections.abc.Sequence" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

class typing.ValuesView(MappingView[VT_co])

   "collections.abc.ValuesView" 的泛型版本。

   3.9 版后已移除: "collections.abc.ValuesView" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。


"collections.abc" 对应的其他类型
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class typing.Iterable(Generic[T_co])

   "collections.abc.Iterable" 的泛型版本。

   3.9 版后已移除: "collections.abc.Iterable" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

class typing.Iterator(Iterable[T_co])

   "collections.abc.Iterator" 的泛型版本。

   3.9 版后已移除: "collections.abc.Iterator" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

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'

   注意，与 typing 模块里的其他泛型不同， "Generator" 的 "SendType" 属
   于逆变行为，不是协变行为，也是不变行为。

   如果生成器只产生值，可将 "SendType" 与 "ReturnType" 设为 "None"：

      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** 和 Generic Alias Type。

class typing.Hashable

   "collections.abc.Hashable" 的别名。

class typing.Reversible(Iterable[T_co])

   "collections.abc.Reversible" 的泛型版本。

   3.9 版后已移除: "collections.abc.Reversible" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

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** 和 Generic Alias Type。

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" 类似，"SendType" 也属于逆变行为。

   如果生成器只产生值，可将 "SendType" 设置为 "None"：

      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** 和 Generic Alias Type。

class typing.AsyncIterable(Generic[T_co])

   "collections.abc.AsyncIterable" 的泛型版本。

   3.5.2 新版功能.

   3.9 版后已移除: "collections.abc.AsyncIterable" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

class typing.AsyncIterator(AsyncIterable[T_co])

   "collections.abc.AsyncIterator" 的泛型版本。

   3.5.2 新版功能.

   3.9 版后已移除: "collections.abc.AsyncIterator" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。

class typing.Awaitable(Generic[T_co])

   "collections.abc.Awaitable" 的泛型版本。

   3.5.2 新版功能.

   3.9 版后已移除: "collections.abc.Awaitable" 现已支持 "[]"。详见
   **PEP 585** 和 Generic Alias Type。


上下文管理器类型
~~~~~~~~~~~~~~~~

class typing.ContextManager(Generic[T_co])

   "contextlib.AbstractContextManager" 的泛型版本。

   3.5.4 新版功能.

   3.6.0 新版功能.

   3.9 版后已移除: "contextlib.AbstractContextManager" 现已支持 "[]"。
   详见 **PEP 585** 和 Generic Alias Type。

class typing.AsyncContextManager(Generic[T_co])

   "contextlib.AbstractAsyncContextManager" 的泛型版本。

   3.5.4 新版功能.

   3.6.2 新版功能.

   3.9 版后已移除: "contextlib.AbstractAsyncContextManager" 现已支持
   "[]"。详见 **PEP 585** 和 Generic Alias Type。


协议
----

这些协议由 "runtime_checkable()" 装饰。

class typing.SupportsAbs

   含抽象方法 "__abs__" 的抽象基类，是其返回类型里的协变量。

class typing.SupportsBytes

   含抽象方法 "__bytes__" 的抽象基类。

class typing.SupportsComplex

   含抽象方法 "__complex__" 的抽象基类。

class typing.SupportsFloat

   含抽象方法 "__float__" 的抽象基类。

class typing.SupportsIndex

   含抽象方法 "__index__" 的抽象基类。

   3.8 新版功能.

class typing.SupportsInt

   含抽象方法 "__int__" 的抽象基类。

class typing.SupportsRound

   含抽象方法 "__round__" 的抽象基类，是其返回类型的协变量。


函数与装饰器
------------

typing.cast(typ, val)

   把值强制转换为类型。

   不变更返回值。对类型检查器而言，代表了返回值具有指定的类型，但运行
   时故意不做任何检查（以便让检查速度尽量快）。

@typing.overload

   "@overload" 装饰器可以修饰支持多个不同参数类型组合的函数或方法。
   "@overload" - 装饰定义的系列必须紧跟一个非 "@overload"-装饰定义（用
   于同一个函数/方法）。"@overload"-装饰定义仅是为了协助类型检查器，
   因为该装饰器会被非 "@overload"-装饰定义覆盖，后者用于运行时，而且会
   被类型检查器忽略。在运行时直接调用 "@overload" 装饰的函数会触发
   "NotImplementedError"。下面的重载示例给出了比联合类型或类型变量更精
   准的类型：

      @overload
      def process(response: None) -> None:
          ...
      @overload
      def process(response: int) -> tuple[int, str]:
          ...
      @overload
      def process(response: bytes) -> str:
          ...
      def process(response):
          <actual implementation>

   详见 **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*。用于类时，递归地应用于该类中定义的所有
   方法，（但不影响超类或子类中定义的方法）。

   本方法可直接修改函数。

@typing.no_type_check_decorator

   让其他装饰器具有 "no_type_check()" 效果的装饰器。

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

@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__" 相同。此外，可通过在 "globals"
   与 "locals" 命名空间里进行评估，以此来处理编码为字符串字面量的前向
   引用。如有需要，在默认值设置为 "None" 时，可为函数或方法注解添加
   "Optional[t]"。对于类 "C"，则返回由所有 "__annotations__" 与
   "C.__mro__" 逆序合并而成的字典。

   本函数以递归地方式用 "T" 替换所有 "Annotated[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 版更改: **PEP 593** 的组成部分，添加了 "include_extras" 参数
   。

typing.get_args(tp)

typing.get_origin(tp)

   为泛型类型与特殊类型形式提供了基本的内省功能。

   对于 "X[Y, Z, ...]" 形式的类型对象，这些函数返回 "X" 与 "(Y, Z,
   ...)"。如果 "X" 是内置对象或 "collections" class 的泛型别名， 会将
   其标准化为原始类。如果 "X" 是包含在其他泛型类型中的 "Union" 或
   "Literal"，"(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 新版功能.

class typing.ForwardRef

   用于字符串前向引用的内部类型表示的类。 例如，"List["SomeClass"]" 会
   被隐式转换为 "List[ForwardRef("SomeClass")]"。 这个类不应由用户来实
   例化，但可以由内省工具使用。

   注解:

     **PEP 585** 泛型类型例如 "list["SomeClass"]" 将不会被隐式地转换为
     "list[ForwardRef("SomeClass")]" 因而将不会自动解析为
     "list[SomeClass]"。

   3.7.4 新版功能.


常量
----

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" 引用。局部变量的类型注释不会被评估，因
   此，第二个注解不需要用引号引起来。

   注解:

     Python 3.7 或更高版本中使用 "from __future__ import" 时，函数定义
     时不处理注解， 而是把注解当作字符串存在 "__annotations__" 里，这
     样就不必为注解使用引号。（详见 **PEP 563**）。

   3.5.2 新版功能.
