如何在 python 3.6 中使用类型提示?

How to use type hints in python 3.6?

我注意到 Python 3.5 和 Python 3.6 添加了很多关于静态类型检查的功能,所以我尝试使用以下代码(在 python 3.6,稳定版本中)。

from typing import List

a: List[str] = []
a.append('a')
a.append(1)
print(a)

令我惊讶的是,Python 没有给我错误或警告,尽管 1 附加到 list 应该只包含字符串。 Pycharm 检测到类型错误并给了我一个警告,但它并不明显并且没有显示在输出控制台中,我担心有时我可能会错过它。我想要以下效果:

  1. 如果很明显我使用了错误的类型,如上所示,抛出警告或错误。
  2. 如果编译器不能可靠地检查我使用的类型是对还是错,请忽略它。

这可能吗?也许 mypy 可以做到,但我更愿意使用 Python-3.6 风格的类型检查(如 a: List[str])而不是注释风格(如 # type List[str])用于 mypy。而且很好奇native python 3.6有没有switch来实现我上面说的两点

类型提示完全被 Python 运行时忽略,并且仅由 mypy 和 Pycharm 的集成检查器等第 3 方工具检查。还有各种鲜为人知的第 3 方工具使用类型注释在编译时或运行时进行类型检查,但大多数人使用 mypy 或 Pycharm 的集成检查器 AFAIK。

事实上,我怀疑在可预见的将来类型检查是否会集成到 Python 中——请参阅 PEP 484 (which introduced type annotations) and PEP 526 (which introduced variable annotations), as well as Guido's comments here 的 'non-goals' 部分。

我个人很乐意将类型检查与 Python 更紧密地集成在一起,但似乎整个 Python 社区都没有准备好或愿意进行这样的更改。

最新版本的 mypy 应该能理解 Python 3.6 变量注释语法和注释式语法。事实上,变量注释基本上是 Guido 的想法(Guido 目前是 mypy 团队的一员)——基本上,mypy 和 Python 中对类型注释的支持几乎是同时开发的。

Is that possible? Maybe mypy could do it, but I'd prefer to use Python-3.6-style type checking (like a: List[str]) instead of the comment-style (like # type: List[str]) used in mypy. And I'm curious if there's a switch in native python 3.6 to achieve the two points I said above.

Python 不可能为您做这件事;您 可以 使用 mypy 进行类型检查(PyCharms 内置检查器也应该这样做)。除此之外,mypy不限制你只能输入注释# type List[str],你可以像在Python中那样使用变量注释3.6 所以 a: List[str] 同样有效。

按原样使用 mypy,因为该版本是最新的,您需要安装 typed_ast 并使用 --fast-parser--python-version 3.6 执行 mypy as documented in mypy's docs。这可能很快就会改变,但现在你需要他们运行顺利

更新: 现在不需要 --fast-parser--python-version 3.6

执行此操作后,mypy 会很好地检测到 a: List[str] 上的第二个操作的不兼容性。假设您的文件名为 tp_check.py,其中包含以下语句:

from typing import List

a: List[str] = []
a.append('a')
a.append(1)
print(a)

运行 mypy 加上前面提到的参数(你必须先 pip install -U typed_ast):

python -m mypy --fast-parser --python-version 3.6 tp_check.py

捕获错误:

tp_check.py:5: error: Argument 1 to "append" of "list" has incompatible type "int"; expected "str"

正如在许多其他关于使用 PythonmypyPyCharm 类型提示的类型提示的答案中提到的那样执行验证,而不是 Python 本身。 Python 目前不使用此信息,它仅将其存储为元数据并在执行期间忽略它。

Python 中的类型注释并不意味着类型强制。任何涉及 运行time 静态类型依赖的事情都将意味着根本性的变化,以至于继续调用生成的语言 "Python".

甚至没有意义

请注意 Python 的动态特性确实允许使用纯 python 代码构建外部工具来执行 运行time 类型检查。它会使程序 运行(非常)缓慢,但也许它适合某些测试类别。

可以肯定的是 - Python 语言的基本原理之一是一切都是对象,并且您可以尝试在 运行 时间对对象执行任何操作。如果对象没有符合尝试操作的接口,它将在 运行 时间失败。

本质上是静态类型的语言以不同的方式工作:在 运行 时间尝试时,操作只需要在对象上可用。在编译步骤中,编译器在各处为适当的对象创建空间和槽 - 并且,在不符合要求的类型上,中断编译。

Python 的类型检查允许任意数量的工具准确地做到这一点:在实际 运行 应用程序之前的某个步骤中断并发出警告(但独立于编译本身)。但是语言的性质无法更改为实际上要求对象在 运行 时间内遵守 - 而且在编译步骤本身进行打字和中断本身就是人为的。

虽然,可以预期 Python 的未来版本可能会在 Python 运行 时间本身上合并编译时类型检查 - 最有可能通过和可选的命令行开关。 (我认为它永远不会是默认的——至少不会破坏构建——也许它可以成为发出警告的默认值)

因此,Python 不需要在 运行 时进行静态类型检查,因为它将不再是 Python。但是至少存在一种同时使用动态对象和静态类型的语言——Cython 语言,它在实践中作为 Python 超集工作。人们应该期待 Cython 很快将新的类型提示语法合并为实际的类型声明。 (目前它对可选的静态类型变量使用不同的语法)