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

Rob*_*ose 1 python backwards-compatibility type-hinting

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

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

重复问题的接受答案确实提供了一种方法,使其在2.7中工作,但它没有说明在Python 3中是否也应该正常工作.我将在答案的评论中提出,但我的问题正在寻找兼容Python 2和早期版本的Python 3的东西.

Mic*_*x2a 7

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

  1. 始终使用基于注释的语法:Python 2不支持函数注释; Python 3.0-3.5不支持变量注释.
  2. 使用Python 2.7和3.0 - 3.4时,安装输入模块的后端口.输入模块已添加到Python 3.5中的标准库中,并且必须为早期版本的Python进行pip安装.

另外一个复杂因素是输入模块已经使用新类型多次更新,因为它被添加到Python 3.5.0中的标准库中 - 类型如ClassVar,Deque,Protocol,Text,Type,仅举几例.

如果要使用这些类型并仍支持Python 3.5和3.6,请另外安装typing_extensions模块.您可以在github repo上找到backported类型的完整列表.

基本上,如果你想使用上面链接的github repo中列出的任何类型,并支持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的最新次要版本虽然更新,但更不容易出现问题.

    (typing_extensions如果您只想支持Python 3.5和3.6的最新次要版本,您也可以不使用而离开: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,标准库和流行的第三方库的类型注释集合.

    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会导致类型化或mypy出现许多问题.我忘记了确切的细节,但结果是你可能最好不要使用它(至少目前是这样).

    相反,通过使用类型系统来避免与unicode相关的问题.特别:

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

    如果你需要编写一个需要使用多种字符串的函数,你可以小心使用Union或者这样做AnyStr.