You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 3中如何在成员装饰器中调用另一个成员装饰器

问题分析与解决方案

错误根源

你错误地将@LOGIN_REQUIRED装饰在了ADMIN_REQUIRED这个装饰器函数本身上。LOGIN_REQUIRED是为实例方法设计的装饰器,它期望被装饰的函数第一个参数是MyClass的实例self,但ADMIN_REQUIRED作为装饰器工厂,第一个参数是要装饰的目标函数func。当Python执行这个装饰逻辑时,LOGIN_REQUIRED内部的decorated_function里的self实际上是get_administration_data这个函数对象,而非MyClass的实例,自然找不到_MyClass__check_for_valid_token属性,导致报错。

正确实现方式

方案1:在ADMIN_REQUIRED内部嵌套LOGIN_REQUIRED

去掉ADMIN_REQUIRED上的@LOGIN_REQUIRED装饰,转而在ADMIN_REQUIRED内部先给目标函数应用登录验证装饰,再叠加管理员检查逻辑:

from functools import wraps

class MyClass:
    def _check_for_valid_token(self, username, token):
        # 将双下划线改为单下划线,避免名称修饰问题(符合Python私有约定)
        # 原有的登录验证逻辑,验证失败抛出异常
        pass

    def check_if_admin(self):
        # 管理员验证逻辑,返回布尔值
        return True

    def LOGIN_REQUIRED(func):
        @wraps(func)
        def decorated_function(self, *args, **kwargs):
            self._check_for_valid_token(args[0], args[1])
            return func(self, *args, **kwargs)
        return decorated_function

    def ADMIN_REQUIRED(func):
        # 先为目标函数添加登录验证
        func_with_login = MyClass.LOGIN_REQUIRED(func)
        
        @wraps(func_with_login)
        def decorated_function(self, *args, **kwargs):
            is_admin = self.check_if_admin()
            if not is_admin:
                raise Exception("无管理员权限")
            return func_with_login(self, *args, **kwargs)
        return decorated_function

    @ADMIN_REQUIRED
    def get_administration_data(self, username, token):
        # 返回管理员数据
        return "敏感管理员数据"

方案2:将装饰器移到类外部(更清晰)

把装饰器定义在类外,避免类内部装饰器的self混淆问题,同时保持逻辑分离:

from functools import wraps

def LOGIN_REQUIRED(func):
    @wraps(func)
    def decorated_function(self, *args, **kwargs):
        self._check_for_valid_token(args[0], args[1])
        return func(self, *args, **kwargs)
    return decorated_function

def ADMIN_REQUIRED(func):
    # 先叠加登录验证
    func = LOGIN_REQUIRED(func)
    
    @wraps(func)
    def decorated_function(self, *args, **kwargs):
        if not self.check_if_admin():
            raise Exception("无管理员权限")
        return func(self, *args, **kwargs)
    return decorated_function

class MyClass:
    def _check_for_valid_token(self, username, token):
        # 登录验证逻辑
        pass

    def check_if_admin(self):
        # 管理员验证逻辑
        return True

    @ADMIN_REQUIRED
    def get_administration_data(self, username, token):
        return "敏感管理员数据"

关键注意点

  • 不要用实例方法装饰器去装饰装饰器工厂函数,两者的参数结构完全不同;
  • 双下划线开头的方法会触发Python的名称修饰(name mangling),改为单下划线_check_for_valid_token更简洁,也能达到内部私有目的;
  • 两种方案都保证了LOGIN_REQUIRED的逻辑先执行,再执行管理员验证,符合你的需求。

内容的提问来源于stack exchange,提问作者RandomGuy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 01:39:53