Python函数注释有什么好处?

34

我已经阅读了PEP 3107的前几个部分,但我仍然不明白它们对语言有何好处。在我看来,你可以使用装饰器为函数添加元数据。例如:

def returns(return_type):
  f.return_type = return_type  # <- adding metadata here
  return f

@returns(Foo)
def make_foo(): ...

你也可以为参数添加元数据,如果你利用默认参数,它看起来会很漂亮:

import inspect

def defaults_are_actually_metadata(f):
  names, args_name, kwargs_name, defaults = inspect.getfuncspec(f)
  f.parameter_metadata = dict(zip(names[-len(defaults):], defaults))
  f.__defaults__ = ()
  return f

@defaults_are_actually_metadata
def haul(load="Stuff to be carried.",
         speed_mph="How fast to move the load (in miles per hour)."): ...

我的初步印象是注释是多余的:装饰器可以做到注释所能做的一切(而且更多)。在为函数添加元数据时,为什么注释比装饰器更好?


4
目前,注释有些像实验,有些还在进行中。实际上,在python-ideas邮件列表中最近关于这个主题的讨论可能会有所帮助。 - John Y
@JohnY 我想将你的回答标记为“正确”,但它不是一个“官方”的答案! - allyourcode
3个回答

34

如您所述,相关PEP为3107(为便于参考,附有链接,以防其他人遇到此问题但尚未阅读)。

目前,注释有点像一个实验,也是一项正在进行中的工作。实际上,在python-ideas邮件列表中有一个关于此主题的最近讨论,可能会很有帮助。(提供的链接仅用于月度档案;我发现特定帖子的URL会定期更改。涉及的主题靠近12月初,并标题为“ [Python-ideas]函数注释的约定”。第一个帖子来自Thomas Kluyver,发布于12月1日)

以下是Guido van Rossum在该线程中的一篇文章:

在2012年12月4日11:43 AM,Jasper St. Pierre写道:

确实。我以前看过注释,但从未理解其目的。它似乎是一项没有明确目标设计和实施的功能,社区应该自己发现目标。

Guido的回答:

恰恰相反。有太多的用例看起来立即重要,我们无法确定哪些是最重要的或者如何将它们组合在一起,因此我们决定采取两步方法:第1步,我们设计了语法,而第2步,我们将设计语义。这个想法非常清楚,一旦语法确定,人们就可以自由地尝试不同的语义 - 只是不在stdlib中。这个想法也是,最终,从所有这些实验中,会出现一个适合于stdlib的实验。

Jasper St. Pierre:

那么,如果我可以问,注释的原始目标是什么?PEP给出了

Guido的回答: “从某种程度上来说,它都是。但对我个人而言,主要目标始终是使用一种符号来指定参数和返回值的类型约束(或许还包括其他约束)。我曾经尝试过多种不同的类型组合方式,例如'list [int]'可能意味着一个整数列表,而 'dict [str,tuple [float,float,float,bool]]'可能意味着将字符串映射到由三个浮点数和一个布尔值组成的元组字典。但我认为就此类符号的达成共识要比关于参数注释语法(想想你能反对这两个示例的多少个理由吧:-)要困难得多 - 我一直强烈希望使用“ var:type = default”语法,并将其作为运行时表达式在与默认值同时进行求值。“
Ned Batchelder的一点幽默感: “对我来说,一个说明性的时刻是在PyCon的早期Py3k主题演讲中(也许是在达拉斯或芝加哥?),Guido忘记了“annotation”这个词,然后说:“你知道的,那些不是类型声明的东西?” :-)”

8
我认为第一段已经说明了问题:

因为Python 2.x系列缺乏一种标准的方法来注释函数的参数和返回值

(强调是我的)

有一个标准的方法可以做到这一点,它的优点在于你可以确切地知道注释的位置。

至于你关于有另外一种方法的论点,你也可以对列表推导式提出同样的论点:

out = []
for x in my_iterable:
    out.append(x)

6
他们有两种不同的角色。
注释是参数的文档/注释,而装饰器则转换函数。
Python本身不会将任何特定的意义或重要性附加到注释中。 Python Decorators页面 装饰器动态地改变函数、方法或类的功能,而无需直接使用子类或更改被装饰的函数的源代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接