Python中奇怪的语法解析错误?

7 投票
2 回答
821 浏览
提问于 2025-04-15 21:59

我是不是漏掉了什么?为什么“坏掉”的那部分代码不应该工作?我在用Python 2.6。

#!/usr/bin/env python

def func(a,b,c):
    print a,b,c

#Working: Example #1:

p={'c':3}

func(1,
     b=2,
     c=3,
     )

#Working: Example #2:

func(1,
     b=2,
     **p)

#Broken: Example #3:

func(1,
     b=2,
     **p,
     )

2 个回答

5

在Python中,通常在用逗号分隔的列表的最后,可以多加一个逗号,比如在参数列表和容器字面量中。这样做的主要目的是为了让代码生成变得稍微简单一些(你不需要特别处理最后一个项目,或者处理只有一个元素的元组)。

在语法定义中,**kwargs是单独提出来的,而且不需要额外的可选逗号。就我所能想象的,它在实际应用中对代码生成没有什么帮助(因为**kwargs总是最后一个,所以你不需要特别处理任何东西),所以我不明白为什么Python会支持这个。

9

这里是来自语法的相关内容:

arglist: (argument ',')* (argument [',']
                         |'*' test (',' argument)* [',' '**' test] 
                         |'**' test)

这里的第一行允许在最后一个参数后面加一个逗号,前提是你没有使用可变参数(varargs)或关键字参数(kwargs),这就是为什么你的第一个例子可以工作的原因。不过,如果你指定了kwargs参数,就不允许在它后面加逗号,这在第二行和第三行中有说明。

顺便提一下,这里有一个有趣的点是语法中展示的:

这两种写法都是合法的:

f(a=1, b=2, c=3,)
f(*v, a=1, b=2, c=3)

但这个就不合法:

f(*v, a=1, b=2, c=3,)

不允许在**kwargs后面加逗号是有道理的,因为它必须始终是最后一个参数。不过,我不太明白为什么语言设计者选择不允许我的最后一个例子,可能是个疏忽吧?

撰写回答