如何确保在Python中应用函数装饰器的顺序?

sat*_*oru 0 python decorator decorator-chaining

一些装饰器应该只用在最外层.

增强原始功能并添加配置参数的装饰器就是一个例子.

from functools import wraps

def special_case(f):
    @wraps(f)
    def _(a, b, config_x=False):
        if config_x:
           print "Special case here"
           return
        return f(a, b)
Run Code Online (Sandbox Code Playgroud)

我怎样才能避免这样的装饰器被另一个装饰器装饰?

编辑

让每个人都试图应用新的装饰者担心应用程序顺序真是令人厌恶.

那么,有可能避免这种情况吗?是否可以在不引入新参数的情况下添加配置选项?

Bre*_*arn 5

没有办法阻止它被装饰.你只需记录它需要最后应用并告诉人们不要在另一个装饰器中使用它.

编辑响应您的编辑:在Python 3中,您可以为您的函数提供仅限关键字的参数.这大大减少了变更对功能的现有使用的影响.不幸的是,这仅适用于Python 3.

最终,将装饰器应用于函数只意味着将装饰函数作为参数传递给另一个函数.有没有办法让一个函数(或任何对象)甚至不知道那它被作为参数传递,更别说什么它传递给.您无法了解以后装饰器的原因与在普通函数调用中的原因相同f(g(x)),该函数g无法知道稍后将被调用f.

这是编写装饰器很棘手的一个原因.依赖于大量使用的是传递明确的参数到他们的包裹功能装饰的(如你通过代码a和b)内在地将是脆弱的.幸运的是,很多时候,你可以写一个使用装饰*args并**kwargs因此它可以通过所有不一起装饰功能使用的参数.

如果有人接受你提供的代码,并编写另一个显式只接受a和b作为参数的装饰器,然后调用装饰函数f(a, b, True),那么如果它失败则是它们自己的错误.他们应该知道他们使用的其他装饰器可能已经改变了功能签名.