python - 设置函数属性的装饰器

标签 python attributes decorator python-decorators function-attributes

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

为了让我的生活更简单,我想使用装饰器。下面我尝试在“装饰”函数上设置属性 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):
    ...

但是当我这样做的时候:

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

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

我错过了什么?

最佳答案

您正在检查内部(包装)函数的属性,但在原始(包装)函数上设置它。但是您完全需要一个包装函数:

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

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

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

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

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

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

关于python - 设置函数属性的装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15794419/

相关文章:

python - Pandas 基于更高分辨率的数据重新采样

python - 根据给定条件向现有数据框添加多个新列

c# - 自定义属性 - 仅为私有(private)成员设置属性用法

python单例类装饰器

python - 如何在 django 中编写自定义装饰器?

python - 如何在 tf.while_loop 中使用 tf.scatter_update

python - 具有 5 个数字或 IND/5 个数字的字符串的正则表达式

c++ - 我可以在 g++ 中访问哪些其他隐藏变量(使用宏预定义)?

jsp - 使用表达式语言设置 session 属性

java - Java中的@override和Python中的@decorator的区别