如何在Account类各方法中优雅实现__authorized权限校验?
问题描述
现有一个Account类,包含私有属性__authorized,调用get()方法会获取账户数据并将__authorized设为True。另外有method_1、method_2、method_3等多个账户操作方法,要求每个操作方法执行前都要校验__authorized:若为False则抛出异常。
目前尝试了两种方案,但都比较繁琐:
方案1:手动在每个方法中写入校验逻辑
class Account: def __init__(self): self.__authorized = False def get(self): # 执行获取账户数据的操作 self.__authorized = True def method_1(self): if not self.__authorized: raise Exception("The account is not authorized with the get method!") def method_2(self): if not self.__authorized: raise Exception("The account is not authorized with the get method!") def method_3(self): if not self.__authorized: raise Exception("The account is not authorized with the get method!")
这种方案需要重复编写相同的校验代码,维护成本高,容易遗漏。
方案2:使用装饰器包裹需要校验的方法
def check_account_authorized(func): def wrapper(*args, **kwargs): if not args[0].is_authorized(): raise Exception("The account is not authorized with the get method!") return func(*args, **kwargs) return wrapper class Account: def __init__(self): self.__authorized = False def get(self): # 执行获取账户数据的操作 self.__authorized = True @check_account_authorized def method_1(self): pass @check_account_authorized def method_2(self): pass @check_account_authorized def method_3(self): pass def is_authorized(self): return self.__authorized
这种方案比手动写校验更优,但仍需给每个方法添加装饰器,方法数量多时依然繁琐,且新增方法容易忘记加装饰器。
更优雅的解决方案
可以利用Python的__getattribute__方法,它会拦截对类实例属性(包括方法)的所有访问请求,我们可以在这个方法中统一处理校验逻辑:
class Account: def __init__(self): self.__authorized = False # 定义需要校验的方法列表 self._protected_methods = {'method_1', 'method_2', 'method_3'} def get(self): # 执行获取账户数据的操作 self.__authorized = True def method_1(self): print("执行method_1") def method_2(self): print("执行method_2") def method_3(self): print("执行method_3") def __getattribute__(self, name): # 获取目标属性/方法 attr = super().__getattribute__(name) # 仅对指定方法执行校验 if name in self._protected_methods and callable(attr): if not self.__authorized: raise Exception("The account is not authorized with the get method!") return attr
方案优势
- 无需重复编写校验代码,也不用逐个添加装饰器,一次配置即可覆盖所有目标方法
- 新增需要校验的方法时,只需在
_protected_methods集合中添加方法名即可,维护更便捷 - 校验逻辑集中在一处,后续修改规则只需调整
__getattribute__中的代码
除此之外,也可以使用类装饰器批量为方法添加校验,或者用元类在类创建时自动为指定方法绑定校验逻辑,但__getattribute__的方式更直观简洁,适合这类场景。
内容的提问来源于stack exchange,提问作者user18196171
相关产品推荐
相关产品推荐

