Python函数注释有什么用?

all*_*ode 33 python python-3.x

我已经阅读了PEP 3107中的前几个部分,但我仍然没有得到他们为语言做的好事.在我看来,您可以使用装饰器向函数添加元数据.例如

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

@returns(Foo)
def make_foo(): ...
Run Code Online (Sandbox Code Playgroud)

您也可以向参数添加元数据,如果您利用默认参数,它看起来很漂亮,如下所示:

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)."): ...
Run Code Online (Sandbox Code Playgroud)

至少我最初的印象是注释是多余的:装饰者可以做注释可以做的所有事情(以及更多).在为函数添加元数据时,为什么注释比装饰器更好?

Joh*_*n Y 32

正如您所提到的,相关的PEP是3107(如果其他人遇到此问题尚未阅读,则链接以便于参考).

目前,注释是一种实验,是一种正在进行的工作.实际上在python-ideas邮件列表中有一个关于该主题的最新帖子可能会有所帮助.(提供的链接仅用于月度存档;我发现特定帖子的URL往往会定期更改.有问题的线程在12月初附近,标题为"[Python-ideas]功能注释约定".第一篇文章来自12月1日的Thomas Kluyver.)

这里有一点Guido van Rossum在该帖子中的帖子:

12/24/2012 11:43 AM,Jasper St. Pierre写道:

确实.我之前看过注释,但我从未明白过这个目的.它似乎是一个设计和实现的功能,没有一些目标,社区应该自己发现目标.

圭多的回应:

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

贾斯珀圣皮埃尔:

那么,如果我可以问一下,注释的最初目标是什么?PEP提出了一些建议,但没有留下任何具体内容.它是否设计用于帮助IDE或检查源代码的静态分析工具?应用程序本身可以通过什么来提供特殊行为,比如命令行解析器或运行时静态检查器?

圭多的回应:

几乎所有这些都在某种程度上.但就我个人而言,主要目标始终是为符号指定参数和返回值的类型约束(以及可能的其他约束).我在不同的时间玩弄了特定的组合方式.例如list [int]可能意味着整数列表,而dict [str,tuple [float,float,float,bool]]可能意味着将字符串映射到三个浮点数和一个bool的元组.但我觉得就这样的符号达成共识要比争论注释的语法更难(想想你可以为这两个例子带来多少反对意见:-) - 我一直有强烈的使用欲望"var:type = default"并使类型成为与默认值同时计算的运行时表达式.

来自Ned Batchelder的一点点幽默:

对我来说一个充满希望的时刻是在PyCon的早期Py3k主题演讲中(也许是在达拉斯或芝加哥?),Guido不记得"注释"这个词,并说,"你知道,那些不是类型声明的东西?" :-)


mgi*_*son 8

我认为第一段说明了一切:

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

(强调我的)

采用标准方法执行此操作的优势在于您可以确切地知道注释的位置.

至于你关于另一种方法的论证,你可以针对列表推导做出相同的论证:

out = []
for x in my_iterable:
    out.append(x)
Run Code Online (Sandbox Code Playgroud)


小智 6

他们有两个不同的角色.

当装饰器转换函数时,注释是参数的文档/注释.

Python本身并没有为注释添加任何特定的含义或意义.

Python装饰器页面

装饰器动态地改变函数,方法或类的功能,而不必直接使用子类或更改正在装饰的函数的源代码.