如何在Python 3.6中使用类型提示?
如何在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
。 Pycharm
检测到了类型错误并给了我一个警告,但是这并不明显,也没有显示在输出控制台中,我担心有时候我可能会错过它。我希望有以下效果:
- 如果像上面那样明显地使用了错误的类型,抛出一个警告或错误。
- 如果编译器不能可靠地检查我使用的类型是对还是错,忽略它。
这有可能吗?也许mypy
可以做到,但我更喜欢使用Python 3.6风格的类型检查(如a: List[str]
),而不是mypy
中使用的注释风格(如# type List[str]
)。我很好奇在原生的Python 3.6中是否有一个开关可以实现我上面说的两点。
在Python 3.6中,引入了类型提示(type hints)的功能,可以在代码中指定变量的类型。然而,如何在Python 3.6中使用类型提示呢?某些情况下可以使用mypy来进行类型检查,但是更希望能够像Python 3.6一样使用类型检查,而不是像mypy中那样使用注释(如# type: List[str])的方式。还有人想知道是否有原生的Python 3.6开关可以实现上述两点。事实上,Python本身并不会为我们做这个,但可以使用mypy进行类型检查(PyCharm内置的检查器也可以)。此外,mypy并不限制只能使用注释的方式(如# type List[str]),你同样可以使用Python 3.6中的变量注释的方式(如a: List[str])。在mypy中,因为版本较新,你需要安装typed_ast并使用--fast-parser和--python-version 3.6参数来运行mypy。这样配置后,mypy可以正确检测到对a: List[str]的第二次操作的不兼容性。具体来说,假设你的文件名为tp_check.py,其中包含以下代码:
from typing import List a: List[str] = [] a.append('a') a.append(1) print(a)
在命令行中执行以下命令(首先需要pip install -U typed_ast):
python -m mypy --fast-parser --python-version 3.6 tp_check.py
mypy会捕捉到错误:
tp_check.py:5: error: Argument 1 to "append" of "list" has incompatible type "int"; expected "str"
需要注意的是,正如其他关于类型提示的答案中所提到的,mypy和PyCharm的类型检查器是执行类型验证的工具,而不是Python本身。Python当前并不使用这些信息,它只将其存储为元数据,在执行过程中忽略它。
如何在Python 3.6中使用类型提示?
Python的类型提示是为了供第三方工具(如mypy和Pycharm的集成检查器)使用,Python运行时可以完全忽略它们。实际上,我对类型检查是否会在可预见的未来内置到Python中表示怀疑。在PEP 484(引入类型注释)和PEP 526(引入变量注释)的“非目标”部分以及Guido的评论中都有提到这一点。
个人而言,我很乐意将类型检查更加紧密地与Python集成,但似乎Python社区尚未准备好或愿意进行这样的改变。
最新版本的mypy应该可以理解Python 3.6的变量注释语法和注释样式语法。实际上,变量注释基本上是Guido的创意(Guido目前是mypy团队的一员) - 实际上,对mypy和Python中的类型注释的支持几乎是同时开发的。
我们(MIT CAVE团队)使用type_enforced(纯Python,无依赖项)来进行运行时检查。请注意,这是自我推广,但仍然有帮助。
以上是关于如何在Python 3.6中使用类型提示的原因和解决方法。
Python 3.6中如何使用类型提示?
在Python中,类型注解并不是用于强制类型的。任何涉及运行时静态类型依赖的事情都意味着需要进行如此根本性的更改,以至于甚至不值得继续称之为“Python”语言。
需要注意的是,Python的动态性质允许我们构建一个外部工具,使用纯Python代码来执行运行时类型检查。这将使程序运行速度变慢,但可能适用于某些测试类别。
要确定的是,Python语言的基本原则之一是,一切皆为对象,并且可以在运行时尝试对对象执行任何操作。如果对象没有符合尝试操作的接口,它将在运行时失败。
静态类型的编程语言工作方式不同:操作必须在运行时尝试时对对象可用。在编译步骤中,编译器在各个地方为适当的对象创建空间和槽位,并在不符合类型的情况下中断编译。
Python的类型检查允许任何数量的工具进行这样的操作:在实际运行应用程序之前的步骤中断并发出警告(但与编译本身无关)。但是,语言的性质无法更改为在运行时实际要求对象遵守 - 并且在编译步骤中验证类型并中断将是人为的。
尽管如此,可以预期将来的Python版本可能会通过可选的命令行开关将编译时类型检查纳入到Python运行时本身 - 最有可能的是。 (我认为它永远不会成为默认选项 - 至少不会中断构建 - 也许可以将其设置为发出警告的默认选项)
因此,Python不需要在运行时进行静态类型检查,因为这将使其不再是Python。但是至少存在一种语言同时使用动态对象和静态类型 - Cython语言,实际上它是Python的超集。人们应该期望Cython很快将采用新的类型提示语法,以实现实际的类型声明。 (目前,Cython对可选静态类型变量使用了不同的语法)