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

2024-09-30 20:25:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个类在运行检查,每个函数执行一个检查。我曾想过给装修师增加额外的条件,但这也许不明智。在

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

我要做的是修改函数属性,例如,将don't exec标志用于不运行检查,require auth用于仅在授予身份验证时执行的检查,或者将函数属性order更改为序列检查启动。在

# 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的用法与本案无关?怎么解决呢?在

非常感谢


Tags: and函数authfieldauthenticationreturnifis
2条回答

没有通用的方法来解决你的问题。decorator没有内置的协作工具,甚至不需要保留对原始函数的引用。在

因此,您需要自己制定一个协议,例如,assignOrder将原始函数保存到do_assignment。在

然后在is_authenticated中,您必须查看传递的函数后面是否有一个“real”函数,并使用它。在

您的代码似乎很混乱,尽管您声明自己是不值得尊敬的装饰器。在

我希望你不要相信如果你做了这样的事情:

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返回一个不执行任何操作的函数,以解决该错误,则在重新加载包含该函数的模块之前(在测试场景中,这通常意味着再次运行所有内容),这一点仍然是不可更改的。在

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

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

^{pr2}$

现在,这个decorator可以通过在调用之间的运行时更改is_authenticated模块级变量来随意打开和关闭装饰函数—不需要重新加载模块。在

同样,回到您的标题问题“multiplepython decorators retrieve original function”: 注意,我在上面的包装器代码中添加了functools.wraps装饰器。在最近的Python中,这个函数在修饰函数上设置一个__wrapped__属性,该属性指向最初的修饰函数。在

因此,如果所有的decorator都表现良好并在其包装器上应用functools.wraps,那么您可以通过 使用其__wrapped__属性。在

相关问题 更多 >