Python3的“函数注解”有哪些好的用法?

172 投票
12 回答
59308 浏览
提问于 2025-04-15 23:57

函数注解:PEP-3107

我看到了一段代码,展示了Python3中的函数注解。这个概念很简单,但我想不出为什么Python3要引入这个功能,或者有什么好的用处。也许大家能给我一些启发?

它是怎么工作的:

def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
    ... function body ...

在参数后面的冒号之后的内容就是“注解”,而在->后面的信息是函数返回值的注解。

foo.func_annotations会返回一个字典:

{'a': 'x',
 'b': 11,
 'c': list,
 'return': 9}

那么,拥有这个功能有什么重要意义呢?

12 个回答

49

这个回答有点晚了,不过我觉得现在函数注解的最佳用法是通过PEP-0484MyPy。还有微软的PyRight,它在VSCode中使用,也可以通过命令行使用。

Mypy是一个可选的Python静态类型检查工具。你可以在Python程序中添加类型提示,这个功能是在Python 3.5 beta 1中引入的标准(PEP 484),然后用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
102

函数注解的用法完全取决于你自己。

它们可以用来做文档说明:

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/,了解如何实现类型检查。

95

我觉得这个其实很不错。

我来自学术背景,可以告诉你,注解在像Java这样的语言中,帮助智能静态分析工具变得非常重要。比如说,你可以定义一些语义,比如状态限制、哪些线程可以访问、架构限制等等。然后有很多工具可以读取这些信息,并处理它们,提供比编译器更强的保证。你甚至可以写一些东西来检查前置条件和后置条件。

我觉得在Python中尤其需要这样的东西,因为它的类型比较弱,但实际上并没有什么简单的构造可以让这个过程变得直接,并且成为官方语法的一部分。

注解的用途不仅仅是提供保证。我可以想象如何把我在Java中用的工具应用到Python上。比如,我有一个工具,可以给方法分配特殊的警告,并在你调用这些方法时提醒你要查看它们的文档(例如,想象一下你有一个方法,不应该用负值调用,但从名字上看并不直观)。有了注解,我在Python中技术上可以写出这样的东西。同样,如果有官方语法的话,还可以写一个工具,根据标签来组织一个大类中的方法。

撰写回答