有没有一种方法可以在Python中的向后兼容代码上使用类型提示? [英] Is there a way to use type hinting on back-compatible code in Python?

查看:104
本文介绍了有没有一种方法可以在Python中的向后兼容代码上使用类型提示?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

类似于__future__中的 import print_function 如何允许您在Py​​thon 2代码中使用 print(),是否有__future__中的 import type_hints ?

重复问题的公认答案确实提供了使其在2.7中工作的一种方法,但没有说在Python 3中是否也可以正常工作.我将在答案的注释中提出疑问,但我的问题是寻找与Python 2和早期版本的Python 3兼容的东西.

解决方案

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

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

另一个复杂之处是,自从将输入模块添加到Python 3.5.0的标准库中以来,它使用新类型进行了多次更新-诸如ClassVar,Deque,Protocol,Text,Type等类型仅举几例

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

>

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


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

  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稍后添加了.但是,老实说,要跟踪添加的时间是很困难的,因此,默认情况下使用type_extensions而不用担心是比较安全的.)

  2. 关于mypy:

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

    但是,mypy本身可以用于分析Python 2.7+代码.

  3. 关于排版和Python 3.0-3.2:

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

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

    但是,排版仅跟踪Python 2.7和3.3+的此信息.因此,如果要专门针对Python 3.0-3.2,则需要小心.

  4. 关于unicode_literals和mypy/typeshed:

    有人建议使用 unicode_literals 作为帮助与Python 2/3兼容的技术./p>

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

    相反,请通过使用类型系统来避免与unicode相关的问题.具体来说:

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

    如果您需要编写一个需要使用多种字符串的函数,则可以仔细使用 Union duplicate question does provide one way to make it work in 2.7, but it doesn't say if that should also work fine in Python 3. I'm going to ask in the comments of the answer, but my question is looking for something compatible with both Python 2 and earlier versions of Python 3.

    解决方案

    To use type hints in a fully backwards-compatible way, you will need to...

    1. Always use the comment-based syntax: Python 2 does not support function annotations; Python 3.0-3.5 do not support variable annotations.
    2. Install the backport of the typing module when using Python 2.7 and 3.0 - 3.4. The typing module was added to the standard library in Python 3.5 and must be pip-installed for earlier versions of Python.

    One additional complication is that the typing module was updated several times with new types since it was added to the standard library in Python 3.5.0 -- types like ClassVar, Deque, Protocol, Text, Type, to name just a few.

    If you want to use those types and still support Python 3.5 and 3.6, additionally install the typing_extensions module. You can find a full list of backported types on the github repo.

    Basically, if you want to use any of the types listed in the github repo linked above, and support Python 3.5.0 - 3.6.x, always import them from typing_extensions instead of from typing.


    Some additional details and caveats that you may or may not care about:

    1. About typing_extensions:

      If you plan on using typing_extensions, also pay careful attention if you need to support Python 3.5.0 - 3.5.2. The typing module went through several, often substantial, internal changes since it was first released in Python 3.5.0.

      The typing_extension module tries to bridge between these different internal APIs in a sane way, but there's always the chance that something was overlooked. The latest minor versions of Python 3.5 and Python 3.6 are much more up-to-date though, and so are far less likely to have issues.

      (You might also be able to get away without using typing_extensions if you want to support only the latest minor versions of Python 3.5 and 3.6: several of the types that were missing in Python 3.5.0 and Python 3.6.0 were added later on. But it's honestly hard to keep track of what was added when, so it might be safer to just default to using typing_extensions and not worry about it.)

    2. About mypy:

      If want to use mypy, keep in mind that mypy can be run using only non EOL'd versions of Python 3. So, at time of writing, Python 3.4+.

      However, mypy itself can be used to analyze Python 2.7+ code.

    3. About typeshed and Python 3.0 - 3.2:

      Mypy, and most other PEP 484-compliant type checking tools, rely on typeshed, a collection of type annotations for the standard library and popular 3rd party libraries.

      Typeshed keeps track of when functions and classes were added to the standard library. That way, you can ask tools like mypy to make sure your code works with specific versions of Python and that you didn't accidentally import anything from the future.

      However, typeshed only keeps track of this info for Python 2.7 and 3.3+. So, you need to be careful if you're targeting specifically Python 3.0 - 3.2.

    4. About unicode_literals and mypy/typeshed:

      Some people recommend using unicode_literals as a technique to help with Python 2/3 compatibility.

      However, I believe using unicode_literals causes a number of issues with either typeshed or mypy. I forget the exact details, but the upshot is that you're probably better off not using it (at least for the time being).

      Instead, avoid unicode-related issues by using the type system to your advantage. Specifically:

      • Use typing.Text when something MUST be unicode. This type is aliased to unicode in Python 2 and str in Python 3.
      • Use bytes (or maybe bytearray?) when something MUST be bytes. Be sure to keep in mind that the bytes behaves slightly differently between Python 2 and 3.
      • Use str when that a value should be whatever str means for that particular version of Python.

      If you need to write a function that needs to work with multiple kinds of strings, you can do so with careful use of Union or AnyStr.

    这篇关于有没有一种方法可以在Python中的向后兼容代码上使用类型提示?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆