Python3的"Function Annotations"有哪些好的用途?
Python3的“函数注解”(Function Annotations)的好用途是什么?
最近的一个最佳使用方式是PEP-0484和MyPy。此外,还有微软的PyRight,它被VSCode使用,并可通过CLI获得。
Mypy是Python的可选静态类型检查器。您可以使用Python 3.5 beta 1引入的即将到来的类型注释标准(PEP 484)向Python程序添加类型提示,并使用mypy对它们进行静态类型检查。
用法如下:
from typing import Iterator def fib(n: int) -> Iterator[int]: a, b = 0, 1 while a < n: yield a a, b = b, a + b
更多示例可以在这里找到:Mypy Examples和How You Can Benefit from Type Hints。
此外,还有使用PEP-0484构建的另一个静态分析器pytype。
不幸的是,类型并没有被强制执行。如果我使用您的示例函数输入`list(fib('a'))`,Python 3.7会欣然接受该参数,并抱怨无法比较字符串和整数。
正如PEP-484所解释的那样,Python只提供类型注释。要强制执行类型,您必须使用mypy。
Python3的“函数注释”有哪些好的用途?
在计算机学术背景下,注释被证明对于启用智能静态分析器(如Java)非常有价值。例如,您可以定义语义,如状态限制、允许访问的线程、体系结构限制等,并且有许多工具可以读取并处理这些注释,提供比编译器更多的保证。甚至可以编写检查前置条件/后置条件的工具。
我认为,由于Python的弱类型,这样的功能在Python中尤为重要,但实际上没有任何构造使其变得简单明了并成为官方语法的一部分。
注释还有其他用途。我可以看到我可以将我的基于Java的工具应用于Python。例如,我拥有一个工具,允许您为方法分配特殊警告,并在调用它们时提醒您应该阅读其文档(例如,想象一下您有一个不能使用负值调用的方法,但从名称上不直观)。使用注释,我可以在Python中编写类似的工具。类似地,如果有一种官方语法,可以编写一个基于标签的工具,根据标签对大型类中的方法进行组织。
我认为这些都是理论上的好处,只有在标准库和第三方模块都使用函数注释并使用一致的含义和注释系统时才能实现。在那一天(永远不会到来)之前,Python函数注释的主要用途将是其他答案中描述的独立使用。在当前情况下,您可以忘记智能静态分析器、编译器保证、基于Java的工具链等。
即使没有所有内容都使用函数注释,您仍然可以在具有函数注释的输入并调用其他同样注释的代码中使用它们进行静态分析。在较大的项目或代码库中,这仍然是进行基于注释的静态分析的重要代码。
据我所知,您可以使用装饰器来实现所有这些,装饰器早于注释。因此,我仍然看不到好处。我对这个问题有稍微不同的看法:stackoverflow.com/questions/13784713/…
快进到2015年,python.org/dev/peps/pep-0484和mypy-lang.org开始证明所有不信者的错误。
它还更加展示了Python对Swift的影响。
看到即使是伟大的人有时也会犯错真是令人振奋。(指的是永远不会到来的那一天,但实际上以PEP-484的形式到来了)。尽管如此,对于“深思熟虑”的部分可能存在一些分歧。:D
我很高兴我对那个预测错了 🙂 我们确实从PEP 484获得了标准化的类型和一个大部分有注释的标准库与typeshed。然而,关于类似于Java的工具集的愿望大部分还没有实现。
Python3的"函数注解"的好用途是什么?
函数注解可以用于文档:
def kinetic_energy(mass: 'in kilograms', velocity: 'in meters per second'): ...
它们可以用于前置条件检查:
def validate(func, locals): for var, test in func.__annotations__.items(): value = locals[var] msg = 'Var: {0}\tValue: {1}\tTest: {2.__name__}'.format(var, value, test) assert test(value), msg def is_int(x): return isinstance(x, int) def between(lo, hi): def _between(x): return lo <= x <= hi return _between def f(x: between(3, 10), y: is_int): validate(f, locals()) print(x, y) >>> f(0, 31.1) Traceback (most recent call last): ... AssertionError: Var: y Value: 31.1 Test: is_int
另请参阅http://www.python.org/dev/peps/pep-0362/,了解一种实现类型检查的方法。
这与文档字符串或函数中的显式类型检查相比有何优势?这似乎只会使语言变得更复杂。
我们当然可以不使用函数注解。它们只是提供了一种访问注解的标准方式。这使它们可以被help()、工具提示访问,并可用于内省。
而不是传递数字,您可以创建类型Mass
和Velocity
。
为了充分展示这一点,我会使用def kinetic_energy(mass: 'in kilograms', velocity: 'in meters per second') -> float:
来显示返回类型。这是我在这里的最佳答案。
使用您的代码,有没有一种方法来验证return
注解?它似乎没有出现在locals
中。
你是对的。要么返回值需要保存到一个变量中,要么整个函数需要被包装在一个验证装饰器中。
我设法用装饰器做到了,但不够美观。