标签:变长参数 失效 init final 求值 signature 之间 rev 函数定义
英文原文:https://www.python.org/dev/peps/pep-3107/
采集日期:2020-01-22
PEP: 3107
Title: Function Annotations
Version: $Revision$
Last-Modified: $Date$
Author: Collin Winter collinwinter@google.com, Tony Lownds tony@lownds.com
Status: Final
Type: Standards Track
Content-Type: text/x-rst
Created: 2-Dec-2006
Python-Version: 3.0
Post-History:
本 PEP 引入了一种语法,用于为 Python 函数添加元数据注解(metadata annotation)
因为 Python 2.x 没有为函数参数和返回值提供标准的注解方式,貌似出现了多种工具软件和程序库来填补这一空白。 有些工具利用 PEP 318 中引入的装饰器,而另一些则对函数的文档字符串(docstring)进行解析,以期找到注解信息。
到目前为止已有机制和语法之间存在着巨大差异,本 PEP 旨在提供一种单一的、标准的注解定义方式,以期减少这些差异所引起的混乱。
在开始精确讨论 Python 3.0 函数注释的来龙去脉之前 ,先来大致讨论一下什么是注解:
函数注解只是一种在编译阶段将 Python 表达式与函数的各个部分建立关联的方式,仅此而已。
Python 本身不会为注解关联任何特定的含义或意义。注解表达式是独立存在的,Python 只是让这些表达式可供使用,用法如下文“访问函数注解”所述。
仅当被第三方库解释时,注解才能发挥作用。使用者可以随意使用函数的注解。比如某个程序库可能会把字符串形式的注解用于提供更好的帮助消息,如下所示:
def compile(source: "something compilable",
filename: "where the compilable thing comes from",
mode: "is this a single statement or a suite?"):
...
另一个程序库或许会被用于对 Python 函数和方法提供类型检查功能。它可以利用注解将函数应有的输入和返回类型标识出来,格式可能如下:
def haul(item: Haulable, *vargs: PackAnimal) -> Distance:
...
不过,不论是第一个示例中的字符串还是第二个示例中的类型信息,本身都没有任何意义,一切含义都单独来自第三方库。
参数的注解采用可选表达式的格式,跟在参数名的后面:
def foo(a: expression, b: expression = 5):
...
若用伪语法(pseudo-grammar)表示,现在参数看起来类似 identifier [: expression] [= expression]
。也就是说,注解始终位于参数默认值之前,注解和默认值都是可选的。就像用等号标出默认值一样,这里用冒号把注解标出来。就像默认值一样,在函数定义得以运行时将会对所有注解表达式进行求值。
*args
和 **kwargs
这种可变长参数(excess parameters)的注解方式也是类似的:
def foo(*args: expression, **kwargs: expression):
...
嵌套参数的注解总是跟在参数名的后面,而不是在右括号后面。嵌套参数中的参数不需要全要带有注解:
def foo((x1, y1: expression),
(x2: expression, y2: expression)=(None, None)):
...
到目前为止,还没有给出如何注解函数返回值的示例。以下便是:
def sum() -> expression:
...
也就是说,现在参数列表后面可以跟一个 ->
和一个 Python 表达式。像参数的注解一样,函数定义得以运行时将会对该表达式进行求值。
函数定义的语法【11】现在变成了:
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
funcdef: [decorators] 'def' NAME parameters ['->' test] ':' suite
parameters: '(' [typedargslist] ')'
typedargslist: ((tfpdef ['=' test] ',')*
('*' [tname] (',' tname ['=' test])* [',' '**' tname]
| '**' tname)
| tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
tname: NAME [':' test]
tfpdef: tname | '(' tfplist ')'
tfplist: tfpdef (',' tfpdef)* [',']
lambda
表达式的语法不支持注解。当然 lambda
表达式的语法可以改成支持注解的格式,这需要在参数列表两侧加上括号。但因为以下原因,还是决定不做改动了【12】:
只要一经编译,函数注解就可以通过函数的 __annotations__
属性访问到了。该属性是一个可变(mutable)字典,将参数名称映射为一个代表已求值注解表达式的对象。
在 __annotations__
映射中有一个特殊键 "return"
。仅当提供了函数返回值的注解时,它才会有效。
例如,以下注解:
def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9):
...
将会生成如下 __annotations__
映射:
{'a': 'x',
'b': 11,
'c': list,
'return': 9}
选用 return
键是因为不能与参数名称发生冲突,任何时候想把 return
用于参数名称,都会引发 SyntaxError
。
如果函数没有带注解或是由 lambda
表达式生成的,则 __annotations__
将是一个空的可变字典。
在注解的讨论过程中,已经给出了很多应用案例。下面给出其中一些案例,按其表达的信息做了分组。这里还包括了一些可能用到注解的现有产品和包示例。
为以下特性提供类型信息
其他信息
在显示函数帮助信息时,pydoc
模块应能显示函数的注解。inspect
模块应改为支持注解信息的获取。
函数签名对象应该公开函数的注解。Parameter
对象或其他地方可能需要做出改动。
参考实现已作为修订(revision) 53170 【10】签入 py3k(以前名为“p3yk”)分支中。
【1】 除非特别指出,否则本文中的“函数”一般当作“callable”的同义词来使用。
【2】 https://mail.python.org/pipermail/python-3000/2006-May/002103.html
【3】 http://web.archive.org/web/20070730120117/http://oakwinter.com/code/typecheck/
【4】 http://web.archive.org/web/20070603221429/http://maxrepo.info/
【5】https://mail.python.org/pipermail/python-3000/2006-May/002091.html
【6】 https://mail.python.org/pipermail/python-3000/2006-May/001972.html
【7】 https://mail.python.org/pipermail/python-3000/2006-May/002105.html
【8】 https://mail.python.org/pipermail/python-3000/2006-May/002209.html
【9】 https://mail.python.org/pipermail/python-3000/2006-June/002438.html
【10】 http://svn.python.org/view?rev=53170&view=rev(已失效)
【11】 http://docs.python.org/reference/compound_stmts.html#function-definitions
【12】 https://mail.python.org/pipermail/python-3000/2006-May/001613.html
【13】 http://www.python.org/dev/peps/pep-0362/
【14】 https://mail.python.org/pipermail/python-3000/2006-August/002895.html
【15】 https://mail.python.org/pipermail/python-ideas/2007-January/000032.html
【16】 https://mail.python.org/pipermail/python-list/2006-December/420645.html
【17】 http://www.python.org/idle/doc/idle2.html#Tips(已失效)
【18】 http://www.jython.org/Project/index.html(已失效,最新项目应该是移到 github 的 jython)
【19】 http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython(已失效,最新项目应该是移到 github 的 ironpython2。)
【20】 http://peak.telecommunity.com/PyProtocols.html
【21】 http://www.artima.com/weblogs/viewpost.jsp?thread=155123
【22】 http://www-128.ibm.com/developerworks/library/l-cppeak2/(已失效,大概是 https://www.ibm.com/developerworks/cn/linux/l-cppeak2/index.html)
【23】 http://rpyc.wikispaces.com/(已失效,不妨参考 wiki)
【24】 http://docs.python.org/library/pydoc.html
本文已在公共领域公开。
PEP 3107 函数注解 -- Python官方文档译文 [原创]
标签:变长参数 失效 init final 求值 signature 之间 rev 函数定义
原文地址:https://www.cnblogs.com/popapa/p/PEP3107.html