装饰器设置功能的属性

ric*_*ier 8 python attributes decorator function-attributes python-decorators

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

为了让我的生活更复杂,我只想使用装饰器.下面我尝试permission在'装饰'功能上设置属性- 如下所示.

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):
    ...
Run Code Online (Sandbox Code Playgroud)

但当我这样做时:

fn = do_x
if logged_in_user.access_level == fn.permission_required:
    ...
Run Code Online (Sandbox Code Playgroud)

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

我错过了什么?

Mar*_*ers 19

您正在内部(包装器)函数中设置该属性.你并不需要一个包装函数:

def permission(permission_required):
    def decorator(func):
        func.permission_required = permission_required
        return func
    return decorator
Run Code Online (Sandbox Code Playgroud)

你的装饰者需要返回一些能够取代原始功能的东西.原始函数本身(添加了属性)可以很好地完成,因为你想要做的就是为它添加一个属性.

如果仍需要包装器,则在包装器函数上设置属性:

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
Run Code Online (Sandbox Code Playgroud)

毕竟,您正在使用装饰器返回的包装器替换包装函数,因此这是您要查找属性的对象.