【问题标题】:Is there a way to use type hinting on back-compatible code in Python?有没有办法在 Python 中对向后兼容的代码使用类型提示?
【发布时间】:2018-10-18 14:09:52
【问题描述】:

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

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

duplicate question 的公认答案确实提供了一种使其在 2.7 中工作的方法,但它并没有说明这是否也应该在 Python 3 中正常工作。我将在答案的 cmets 中提问,但我的问题是寻找与 Python 2 和早期版本的 Python 3 兼容的东西。

【问题讨论】:

  • Type hinting in Python 2的可能重复
  • @MaxMalysh 差不多了,但我不只是在寻找 Python 2,还对 Python 3 的早期版本感兴趣。

标签: python backwards-compatibility type-hinting


【解决方案1】:

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

  1. Always use the comment-based syntax:Python 2 不支持函数注解; Python 3.0-3.5 不支持变量注解。
  2. 在使用 Python 2.7 和 3.0 - 3.4 时安装 typing module 的 backport。 Typing 模块已添加到 Python 3.5 的标准库中,并且必须为早期版本的 Python 安装 pip。

另外一个复杂的问题是,类型模块在 Python 3.5.0 中被添加到标准库后,已经多次更新为新类型——诸如 ClassVar、Deque、Protocol、Text、Type 等类型,仅举几例.

如果您想使用这些类型并且仍然支持 Python 3.5 和 3.6,请另外安装 typing_extensions 模块。您可以在 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 只能使用非 EOL 版本的 Python 3 运行。因此,在撰写本文时,Python 3.4+。

    不过,mypy 本身可用于分析 Python 2.7+ 代码。

  3. 关于 typeshed 和 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. 关于 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

【讨论】:

    【解决方案2】:

    对重复问题的接受答案似乎对 x

    来自mypy docs

    下面的例子说明了 Python 2 的函数类型注解 句法。此语法在 Python 3 模式下也有效:

    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

    【讨论】:

      猜你喜欢
      • 2015-08-10
      • 1970-01-01
      • 2016-01-24
      • 2017-10-29
      • 2021-01-04
      • 2021-07-24
      • 2015-04-26
      • 2010-12-26
      • 1970-01-01
      相关资源
      最近更新 更多