Skip to main content
 首页 » 编程设计

python之有没有一种方法可以在Python中的向后兼容代码上使用类型提示

2025年05月04日13lvdongjie

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

与from __future__ import print_function允许您在Py​​thon 2代码中使用print()的方式类似,是否存在from __future__ import type_hints?

接受的duplicate question答案确实提供了使其在2.7中工作的一种方法,但并未说明在python 3中是否也可以正常工作。我要在答案的注释中提出问题,但我的问题是寻找与Python 2和早期版本的Python 3兼容的东西。

请您参考如下方法:

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


Always use the comment-based syntax:Python 2不支持函数注释; Python 3.0-3.5不支持变量注释。
使用Python 2.7和3.0-3.4时,安装typing module的反向端口。键入模块已添加到Python 3.5的标准库中,并且必须通过pip安装用于早期版本的Python。


另一个麻烦是,自从将输入模块添加到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导入它们。



您可能会或可能不会关心的一些其他详细信息和警告:


关于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中缺少的几种类型坦白地说,要跟踪添加的内容确实很困难,因此默认情况下使用typeing_extensions而不用担心它会更安全。)
关于mypy:

如果要使用mypy,请记住,只能使用非EOL版本的Python 3运行mypy。因此,在编写本文时,Python 3.4+。

但是,mypy本身可用于分析Python 2.7+代码。
关于打字机和Python 3.0-3.2:

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

Typeshed跟踪何时将函数和类添加到标准库。这样,您可以要求诸如mypy之类的工具来确保您的代码可用于特定版本的Python,并且您不会在将来意外导入任何内容。

但是,排版仅跟踪Python 2.7和3.3+的此信息。因此,如果要专门针对Python 3.0-3.2,则需要小心。
关于unicode_literals和mypy / typeshed:

有人建议使用unicode_literals作为有助于Python 2/3兼容性的技术。

但是,我相信使用unicode_literals会导致很多打字错误或mypy问题。我忘记了确切的细节,但是结果是您最好不要使用它(至少暂时是这样)。

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


当某些内容必须是unicode时,请使用typing.Text。此类型在Python 2中别名为unicode,在Python 3中别名为str。
当某些内容必须为字节时,请使用bytes(或bytearray?)。请记住,bytes在Python 2和3之间的行为略有不同。
当值应为该特定版本的Python的str含义时,请使用str。


如果您需要编写一个需要使用多种字符串的函数,则可以谨慎使用Union或AnyStr来实现。