Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python装饰程序中的SyntaxError_Python_Syntax Error_Decorator - Fatal编程技术网

Python装饰程序中的SyntaxError

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

为什么下面的Python代码片段是:

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()
不算数,因为我不指望你会需要它)。”