假设我有一个装饰工厂工厂。这是非常无用的,仅累加参数并添加到结果中,仅作为示例:

def decorator_factory_factory(a):
    def decorator_factory(b):
        def decorator(f):
            def decorated(*args, **kwargs):
                return f(*args, **kwargs) + a + b
            return decorated
        return decorator
    return decorator_factory

我尝试像这样使用它:
@decorator_factory_factory(3)(1)
def should_return_5():
    return 1

我收到一个SyntaxError。当然应该允许任何Python表达式作为装饰器吗?

我也尝试过:
@(decorator_factory_factory(3)(1))
def should_not_be_touched():
    return 1

但这是另一个SyntaxError。

难道我做错了什么?我发现的唯一方法是:
_decorator_factory = decorator_factory_factory(3)
@_decorator_factory(1)
def should_not_be_touched():
    return 1
del _decorator_factory

但这需要一个附加变量,需要将其删除

最佳答案

更新:从Python 3.9开始,这不再是语法错误。参见PEP 614

装饰器语法is restricted。您不允许使用任意表达式。您被允许使用.运算符,最后最多只能调用一个(),因此

@decorator_factory_factory(3)(1)
def should_return_5():
    return 1
是语法错误,因为它的调用(3)不在结尾。
实际上,这不是限制,因为装饰器只是函数声明后的赋值糖。您可以不受限制地自己做,
def should_return_5():
    return 1
should_return_5 = decorator_factory_factory(3)(1)(should_return_5)
不会创建需要删除的其他变量。
此外,单个函数调用足以通过简单的标识函数潜入任意表达式。
def identity(x):
    return x

@identity(decorator_factory_factory(3)(1))
def should_return_5():
    return 1
使用identity的短名称(不是id,这是内置的),这与您想要的@(decorator_factory_factory(3)(1))语法非常接近。

关于python - 为什么使用装饰器工厂工厂函数会出现语法错误?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44358027/

10-14 18:19