装饰器设置函数的属性 [英] decorator to set attributes of function

查看:20
本文介绍了装饰器设置函数的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望仅当登录用户具有所需的权限级别时才能执行不同的功能.

I want different functions to be executable only if the logged in user has the required permission level.

为了让我的生活更简单,我想使用装饰器.下面我尝试在 'decorated' 函数上设置属性 permission - 如下所示.

To make my life more simple I want to use decorators. Below I attempt to set attribute permission on 'decorated' functions - as shown below.

def permission(permission_required):
    def wrapper(func):
        def inner(*args, **kwargs):
            setattr(func, 'permission_required', permission_required)
            return func(*args, **kwargs)
        return inner
    return wrapper

@permission('user')
def do_x(arg1, arg2):

    ...

@permission('admin')
def do_y(arg1, arg2):
    ...

但是当我这样做时:

fn = do_x
if logged_in_user.access_level == fn.permission_required:
    ...

我得到一个错误 'function' object has no attribute 'permission_required'

我错过了什么?

推荐答案

您正在检查内部(包装)函数的属性,但将其设置在原始(包装)函数上.但是你需要一个包装函数:

You are checking the attribute on the inner (wrapper) function, but set it on the original (wrapped) function. But you need a wrapper function at all:

def permission(permission_required):
    def decorator(func):
        func.permission_required = permission_required
        return func
    return decorator

你的装饰器需要返回一些东西来替换原来的函数.原始函数本身(添加了属性)就可以了,因为您要做的就是为其添加一个属性.

Your decorator needs to return something that'll replace the original function. The original function itself (with the attribute added) will do fine for that, because all you wanted to do is add an attribute to it.

如果你还需要一个包装器,那么在 包装器函数上设置属性:

If you still need a wrapper, then set the attribute on the wrapper function instead:

from functools import wraps

def permission(permission_required):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # only use a wrapper if you need extra code to be run here
            return func(*args, **kwargs)
        wrapper.permission_required = permission_required
        return wrapper
    return decorator

毕竟,您正在用装饰器返回的包装器替换包装的函数,所以这就是您要在其上查找属性的对象.

After all, you are replacing the wrapped function with the wrapper returned by the decorator, so that's the object you'll be looking for the attribute on.

我还添加了 @functools.wraps() 装饰器到包装器,它将重要的识别信息和其他有用的东西从 func 复制到包装器,使其更易于使用.

I also added the @functools.wraps() decorator to the wrapper, which copied across important identifying information and other helpful things from func to the wrapper, making it much easier to work with.

这篇关于装饰器设置函数的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆