Python是否允许调用decorator工厂?

Python是否允许调用decorator工厂?,python,grammar,Python,Grammar,对,他有一个。在这篇文章中,他举了一个例子: def decorator_factory_factory(method): def decorator_factory(regex): def decorator(f): def inner(*args, **kwargs): # do stuff with f(*args, **kwargs) # and method and rege

对,他有一个。在这篇文章中,他举了一个例子:

def decorator_factory_factory(method):
    def decorator_factory(regex):
        def decorator(f):
            def inner(*args, **kwargs):
                # do stuff with f(*args, **kwargs)
                # and method and regex
            return inner
        return decorator
    return decorator_factory
然后,他举了一个例子,说明如何给装饰师打电话:

@decorator_factory_factory('GET')('^/.*$')
def onGetAnything(self):
    pass
这引起了我的注意。我以前从未尝试过调用decorator decorator工厂,因此我决定查看代码的行为:

>>> def decorator_factory_factory(method):
    def decorator_factory(regex):
        def decorator(f):
            def inner(*args, **kwargs):
                print(args, kwargs)
            return inner
        return decorator
    return decorator_factory

>>> @decorator_factory_factory('GET')('^/.*$')
def onGetAnything(self):
    pass
SyntaxError: invalid syntax
>>> 
从上面可以看到,Python引发了一个
SyntaxError
。为什么呢?除了显然为麦克拉肯先生工作的代码外,这类代码似乎应该运行得很好。它的语法是否与将函数调用链接在一起的语法基本相同?例如:

>>> def foo():
    def bar():
        return 2
    return bar

>>> foo()()
2
>>>
我想他可能使用的是一个较旧的Python版本,允许使用这种语法,所以我查看了Python版本的语法,他在2009年写这篇文章时可能使用的语法;2.6.9. 但似乎仍然不允许链式装饰调用:


在任何Python版本中都允许使用这种语法吗。如果没有,那么伊恩是如何运行他的代码的呢?他只是犯了一个错误吗?

作为一种解决方法,要让它正常工作,你可以让一个
装饰者\u调用者
装饰者,为你打电话:

def decorator_caller(decorator, args_list):
    d = decorator
    for args in args_list:
        d = d(*args)
    return d
这样使用:

@decorator_caller(decorator_factory_factory, (('GET',), ('^/.*$',)))
def onGetAnything(self):
    pass
或者改用列表(因为单项元组看起来很混乱):


请注意,我不认为这样一个工厂是一个有用的东西来建立。当外部工厂真的会影响内部工厂的逻辑时,工厂工厂是有意义的。如果您所做的只是创建一个临时工厂来创建单个项目,只是为了立即扔掉该工厂,那么除了更复杂和更差的总体性能之外,您实际上什么也得不到

如果您实际将工厂存储在周围以供重用,则这将是另一回事:

getFactory = decorator_factory_factory('GET')

@getFactory('^/index.*$')
def index():
    pass

@getFactory('^/.*$')
def x():
    pass

这很有意义,语法也很好。但是,如果您只是想通过链接工厂调用来添加另一个参数来配置装饰器,那么您应该调整工厂以同时使用这两个参数。

几乎可以肯定,这只是shell缩进函数定义。改为在文件中执行此操作。@DanielRoseman不。我不认为文章中提供的例子是有效的。decorator工厂可以用来生成decorator
GET=decorator\u factory\u factory('GET')
->
@GET('regex')
,但我认为不可能按照作者描述的方式使用decorator。可能是误导。我很乐意出错并得到详细的解释,但它看起来不像是开箱即用的python行为。@Taras“我很乐意出错并得到详细的解释”——你和我都是。虽然我开始认为你是对的,而伊恩只是犯了个错误。我怀疑最初的博主是否真的尝试过。他写道(缩短):“我本可以使用这个函数……它完全不可读,所以划清界限……”谢谢你的回答。你的权利,你必须把工厂储存起来。我真的只是想知道这是否可能。但我猜答案似乎是“不”,因为我所研究的所有Python版本语法都会拒绝这种语法。甚至早在2.4版本。
@decorator_caller(decorator_factory_factory, (['GET'], ['^/.*$']))
def onGetAnything(self):
    pass
getFactory = decorator_factory_factory('GET')

@getFactory('^/index.*$')
def index():
    pass

@getFactory('^/.*$')
def x():
    pass