有没有办法在 Python 中的向后兼容代码上使用类型提示?

Is there a way to use type hinting on back-compatible code in Python?

我正在编写一些代码,我希望能够在添加类型提示之前在 Python 的先前版本上 运行,而无需单独的代码库。有没有简单的方法可以做到这一点?

类似于 from __future__ import print_function 允许您在 Python 2 代码中使用 print() 的方式,是否有 from __future__ import type_hints

的公认答案确实提供了一种使其在 2.7 中工作的方法,但它没有说明这是否也应该在 Python 中正常工作 3. 我要走了在答案的评论中提问,但我的问题是寻找与 Python 2 和 Python 3.

的早期版本兼容的东西

重复问题的已接受答案似乎对 Python 3.x 有效,其中 x < 5,至少对 mypy 是这样。

来自mypy docs

The example below illustrates the Python 2 function type annotation syntax. This syntax is also valid in Python 3 mode:

from typing import List

def hello(): # type: () -> None
    print 'hello'

class Example:
    def method(self, lst, opt=0, *args, **kwargs):
        # type: (List[str], int, *str, **bool) -> int
        """Docstring comes after type comment."""

但是在 Python 3.5 之前,您需要 pip install typing.

要以完全向后兼容的方式使用类型提示,您需要...

  1. :Python2 不支持函数注解; Python 3.0-3.5 不支持变量注解。
  2. 使用 Python 2.7 和 3.0 - 3.4 时安装 typing module 的反向端口。 typing 模块已添加到 Python 3.5 的标准库中,并且必须为 Python.
  3. 的早期版本安装 pip-installed

另一个复杂的问题是,自从在 Python 3.5.0 中将输入模块添加到标准库后,输入模块用新类型进行了多次更新——类型如 ClassVar、Deque、Protocol、Text、Type , 仅举几例。

如果您想使用这些类型并仍然支持 Python 3.5 和 3.6,请额外安装 typing_extensions module. You can find a full list of backported types on the github repo.

基本上,如果您想使用上面链接的 github 存储库中列出的任何类型,并支持 Python 3.5.0 - 3.6.x,请始终导入它们来自 typing_extensions 而不是来自 typing.


您可能关心或不关心的一些额外细节和注意事项:

  1. 关于typing_extensions:

    如果您打算使用 typing_extensions,如果您需要支持 Python 3.5.0 - 3.5.2,还要特别注意。自从在 Python 3.5.0 中首次发布以来,打字模块经历了多次内部更改,通常是实质性的更改。

    typing_extension 模块试图以一种理智的方式在这些不同的内部 API 之间架起桥梁,但总是有可能忽略某些东西。 Python 3.5 和 Python 3.6 的最新次要版本更新得多,因此出现问题的可能性要小得多。

    (如果您只想支持 Python 3.5 和 3.6 的最新次要版本,您也可以不使用 typing_extensions:Python 3.5.0 和 Python 3.6.0 是后来添加的。但是老实说很难跟踪添加的内容,所以默认使用 typing_extensions 和不用担心。)

  2. 关于mypy:

    如果想使用 mypy,请记住 mypy 可以 运行 仅使用 Python 的非 EOL 版本 3。因此,在撰写本文时,Python 3.4+.

    不过mypy本身可以用来分析Python 2.7+代码

  3. 关于打字和 Python 3.0 - 3.2:

    Mypy 和大多数其他符合 PEP 484 的类型检查工具依赖于 typeshed,标准库和流行的第 3 方库的类型注释集合。

    Typeshed 跟踪函数和 类 何时添加到标准库中。这样,您就可以请求 mypy 等工具来确保您的代码适用于特定版本的 Python,并且您不会不小心从未来导入任何内容。

    但是,typeshed 仅跟踪 Python 2.7 和 3.3+ 的此信息。因此,如果您专门针对 Python 3.0 - 3.2.

  4. ,则需要小心
  5. 关于unicode_literals和mypy/typeshed:

    有些人建议使用 unicode_literals 作为一种技术来帮助实现 Python 2/3 兼容性。

    但是,我认为使用 unicode_literals 会导致 typeshed 或 mypy 出现许多问题。我忘记了具体的细节,但结果是你最好不要使用它(至少暂时)。

    相反,通过使用对您有利的类型系统来避免与 unicode 相关的问题。具体来说:

    • 当某些内容必须是 unicode 时使用 typing.Text。此类型别名为 Python 2 中的 unicode 和 Python 3 中的 str
    • 当某些东西必须是字节时使用bytes(或者可能bytearray?)。请务必记住 bytes 在 Python 2 和 3 之间的行为略有不同。
    • 当值应该是 str 对 Python.
    • 的特定版本意味着什么时使用 str

    如果您需要编写一个需要处理多种字符串的函数,您可以谨慎使用 UnionAnyStr.