哪个语法规则符合 def foo(a, *, b=10) 这个复合语句?

4
在函数定义中,参数的正式语法如下:(参考链接)
parameter_list ::=  (defparameter ",")*                                        #[1]
                    | "*" [parameter] ("," defparameter)* ["," "**" parameter] #[2]
                    | "**" parameter                                           #[3]
                    | defparameter [","] )                                     #[4]

(为了更清楚,我添加了#[num]

符号 | 表示或,根据这个表示法。

我无法看出它如何与下面的函数定义完全匹配:

def foo(a, *, b=10): pass

显然,人们可以认为一个形如def foo(a, *, b=10)的定义属于规则#[2],该规则允许使用*符号来分隔仅限关键字参数。但是对于foo函数的规则,我认为应该结合#[1]#[2]两个规则:
parameter_list ::= (defparameter ",")* "*" [parameter] ("," defparameter)* ["," "**" parameter] 

由于规则#[1]#[2]本身似乎不能单独匹配该情况。

我在这里漏掉了什么?


你有往下看吗?如果一个参数有默认值,在“*”之前的所有后续参数也必须有默认值 - 这是一种语法限制,语法本身并没有表达出来。 - Bhargav Rao
这句话的意思是调用类似于 def foo(*, a, b=10) 的形式是不合法的,对吗? - Dimitris Fasarakis Hilliard
1
看起来有问题,除非我也漏掉了什么。最后一个闭括号没有对应的开括号。 - Ry-
1
@Jim 很有趣。我不确定,但我猜它一定是#2。 (等待答案) - Bhargav Rao
@BhargavRao,显然这只是一个愚蠢的小错误,导致我把所有东西都读错了。这些错误真是让人沮丧。 - Dimitris Fasarakis Hilliard
1
天啊,这个世界怎么了?文档里居然有错别字! - Bhargav Rao
2个回答

2

嗯,正如Ryan所指出的那样,这明显是文档中的一个错误。

以下是Python v3.5.0版本中函数声明语法的实际语法规则定义:(链接)

funcdef: 'def' NAME parameters ['->' test] ':' suite

parameters: '(' [typedargslist] ')'

typedargslist: (tfpdef ['=' test] (',' tfpdef ['=' test])*
    [',' ['*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]] | '**' tfpdef [',']]]
  | '*' [tfpdef] (',' tfpdef ['=' test])* [',' ['**' tfpdef [',']]]
  | '**' tfpdef [','])

这里,tfpdef是标识符

。在IT技术中使用的标识符通常用来表示变量、函数和其他编程元素。

tfpdef: NAME [':' test]

testexpression是相同的。

test: or_test ['if' or_test 'else' test] | lambdef

2
正式语法似乎缺少一个左括号。最后一个右括号没有匹配到任何内容,如果您查看Python 2版本,就会非常清楚:链接
parameter_list ::=  (defparameter ",")*
                    (  "*" identifier ["," "**" identifier]
                    | "**" identifier
                    | defparameter [","] )

所以,请将其理解为:
parameter_list ::=  (defparameter ",")*
                    ( "*" [parameter] ("," defparameter)* ["," "**" parameter]
                    | "**" parameter
                    | defparameter [","] )

有人可能在重新排版时将 ( 替换为了 |


我明天早上会尝试提交一个问题...但是问题跟踪器很难搜索... - Ry-
是的,那确实很有道理。如果他们最终回复了,请尽量记得将其添加到您的答案中。 - Dimitris Fasarakis Hilliard

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