Python装饰程序中的SyntaxError
为什么下面的Python代码片段是:Python装饰程序中的SyntaxError,python,syntax-error,decorator,Python,Syntax Error,Decorator,为什么下面的Python代码片段是: def f(): def g(): def h(x): pass return h return g @f()() def i(): pass 引发一个语法错误 @f()() ^ SyntaxError: invalid syntax 因为据我所知,decorator是可调用的,只有一个必需的位置参数,也就是说,这些是有效的decorator: de
def f():
def g():
def h(x):
pass
return h
return g
@f()()
def i():
pass
引发一个语法错误
@f()()
^
SyntaxError: invalid syntax
因为据我所知,decorator是可调用的,只有一个必需的位置参数,也就是说,这些是有效的decorator:
def f(x):
pass
def g(x, y=3):
pass
class A:
def __init__(self, x):
pass
class B:
def __init__(self, x, y=3):
pass
它们被用作:
def h():
pass
h = f(h)
h = g(h)
h = A(h)
h = B(h)
class C:
pass
C = f(C)
C = g(C)
C = A(C)
C = B(C)
或者通过@expression
语句,其中expression
应计算为修饰符,后面应是函数或类定义或另一个@expression
语句:
@f
def h():
pass
@g
def h():
pass
@A
def h():
pass
@B
def h():
pass
@f
class C:
pass
@g
class C:
pass
@A
class C:
pass
@B
class C:
pass
以下@expression
语句完全有效:
def f():
def g():
def h(x):
pass
return h
return g
def g(x):
def h(x):
pass
return g
@g(f()())
def h():
pass
那么,为什么顶部的那个不是呢?因为这是一个语法错误,我们必须转到语法:
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
@
后面的部分不是任意表达式;它是一个带有一个可选参数列表的单一名称
我意识到这并不能回答为什么语法是这样写的问题,但除了“就是这样”之外,我没有任何答案。这是一个非常好的问题。更能说明问题的可能是,在您的第一个代码片段之后,如果您执行
z=f()
,则@z
是有效的。我终于找到了原因。它是。可能对基本原理部分有用“decorator语句在它可以接受的范围内是有限的——任意表达式将不起作用。Guido出于直觉更喜欢这样。”来自Python开发人员讨论中的“PEP 318——函数和方法的Decorators”,许多人似乎反对限制@expression
语法:“我想我有相反的直觉:语法中的特殊表达式类总是不好的。”@Maggyero Guido似乎只是指支持任意表达式,而嵌套函数调用可能可以通过'@'虚线名称[(“(“[arglist]”)NEWLINE
。最初的修补程序将自身限制为一个参数列表(尽管这可能使语法不再是LL(1)),这有点令人惊讶。但Guido并不反对将来取消该限制:"我对这个有一种直觉。我不确定它来自哪里,但我有它。这可能是我希望编译器能够识别某些装饰符。因此,虽然将来将语法更改为@test
非常容易,但我希望继续使用更受限制的形式,除非出现真正的用例,其中降低@test
会增加可读性。(@foo().bar()
不算数,因为我不指望你会需要它)。”