多个python装饰器检索原始函数

多个python装饰器检索原始函数,python,decorator,Python,Decorator,我有一个类运行检查,每个函数执行一个检查。我曾想给装饰师增加额外的条件,但这可能并不明智 我理解decorators的概念,每个decorator都将它所修饰的函数作为输入,然后返回到下一个被修饰的函数。例如,对于返回字符串的函数来说,这非常有效,因为decorator可以轻松编辑输出并将其返回给下一个decorator 我要做的是修改函数属性,例如,为不运行的检查设置一个不执行标志,仅在授予身份验证的情况下执行的检查需要验证,或者更改函数属性顺序,以按顺序启动检查 # I return f o

我有一个类运行检查,每个函数执行一个检查。我曾想给装饰师增加额外的条件,但这可能并不明智

我理解decorators的概念,每个decorator都将它所修饰的函数作为输入,然后返回到下一个被修饰的函数。例如,对于返回字符串的函数来说,这非常有效,因为decorator可以轻松编辑输出并将其返回给下一个decorator

我要做的是修改函数属性,例如,为不运行的检查设置一个
不执行
标志,
仅在授予身份验证的情况下执行的检查需要验证
,或者更改函数属性
顺序
,以按顺序启动检查

# I return f only if is_authenticated flag is True
def auth_required(is_authenticated):
    def check_authentication(f):
        if is_authenticated:
            return f
    return check_authentication

# I edit order variable
def assignOrder(order):
    def do_assignment(f):
        f.order = order
        return f
    return do_assignment
# I instanciate Checks class and provide authentication;
# login and password will be tried and is_authenticat flag set accordingly
c = Checks(target, login, password)

# I sort on order variable and launch checks
functions = sorted(
    [
        getattr(c, field) for field in dir(c)
        if hasattr(getattr(c, field), 'order')
    ],key = (lambda field : field.order) 
)
for function in functions:
    function()

# I assign decorators so that order variable is set 
# I would like auth_required triggers launch if auth is performed
@auth_required(True)
@assignOrder(100)
def check_shares(self):
    # check defined here
这对assignOrder非常有效,我的支票是按正确的顺序启动的

但是
@auth_required
应用于
assignOrder
,这不是我想要的

有没有办法检索要修饰的原始函数?或者在这种情况下,decorator的用法是不相关的?解决办法是什么


非常感谢

解决您的问题没有通用的方法。装饰器没有内置的协作功能,甚至不需要保留对原始函数的引用

因此,您需要自己制定一个协议,例如制作
assignOrder
将原始函数保存到
do\u assignment


然后,在
经过身份验证的情况下
,您必须查看传递的函数后面是否有“真实”的函数,并使用它。

尽管您声明不支持装饰程序,但您的代码似乎很混乱

我希望你能理解,如果你做了以下事情:

def auth_required(is_authenticated):
    def check_authentication(f):
        if is_authenticated:
            return f
    return check_authentication

@auth_required(something)
def my_function():
    ....
这意味着在导入时检查“something”变量,并且只检查一次,并且您的修饰函数将被抑制-即名称“mu_function”将绑定到
None
,从而在尝试调用该变量的任何代码中导致错误。如果您替换return None来返回一个不执行任何操作的函数,以解决该错误,那么在重新加载包含该函数的模块之前,这仍然是不可更改的(在测试场景中,这通常意味着再次运行所有功能)

所以,这不仅仅是错的——它表明你对装饰师的所作所为感到困惑

使用全局变量以这种方式打开和关闭函数会更简单:

from functools import wraps
def auth_required(f):
   @wraps(f)
   def wrapper (*args, **kw):
       if is_authenticated:
            return f(*args, **kw)
       return None
   return wrapper
现在,此装饰程序可以通过在调用之间的运行时更改
is\u authenticated
模块级变量来随意打开和关闭装饰函数-无需重新加载模块

另外,回到您关于“多个python装饰器检索原始函数”的标题问题: 注意我在上面的包装器代码本身中添加了
functools.wrapps
decorator。在最近的Python中,该函数在修饰函数上设置一个
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
属性,该属性指向最初的修饰函数

因此,如果您的所有装饰程序都表现良好,并且在其包装上应用了
functools.wrapps
,则您始终可以通过
使用其
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

“但是@auth_required应用于assignOrder,这不是我想要的。”实际上,
auth_required
应用于“what
assignOrder
returned”,而不是
assignOrder
本身。你真正的问题是什么?谢谢你的回答;我的问题是我不能同时设置
authenticated
标志和分配
订单
。我编辑了我的问题,以便它是清晰的。我恐怕我不明白你的
auth_required
decorator应该如何工作???我在别处对用户进行身份验证,并用身份验证的结果填充这个decorator参数:
True
是理所当然的,
False
是禁止的。我仍然不知道它应该如何工作,很抱歉通过定义和应用
auth\u require()
,您的修饰函数将变成
check\u authentication(f)
。这个函数的作用是:1。检查
是否经过身份验证
是否为真-这将始终为真,因为在此阶段
经过身份验证
是原始函数(您用
auth\u required()
修饰的函数),并且
函数
对象在布尔上下文中具有真值-然后为2。返回它的参数
f
。这显然不是你所期望的,是吗???