如何基于__init__参数控制对象实例的指定方法访问权限
实现方案
你之前对装饰器的适用场景存在误解:装饰器本身的绑定逻辑确实在类定义阶段执行,但装饰器包裹的校验逻辑会在方法被实例调用时才运行,此时实例已经完成初始化,可以正常获取实例属性,因此装饰器是完全适用的,以下是两种符合DRY原则的实现方案:
方案1:通用方法装饰器(推荐,灵活度高)
适合需要零散限制部分方法的场景,只需要给目标方法加装饰器即可,无需修改类的核心逻辑:
# 通用限制装饰器 def restrict_if(flag_attr: str, error_cls=Exception, error_msg: str = "当前方法无访问权限"): def decorator(method): def wrapper(self, *args, **kwargs): # 调用方法时才校验实例属性 if getattr(self, flag_attr, False): raise error_cls(error_msg) return method(self, *args, **kwargs) return wrapper return decorator # 业务类实现 class NewClass: def __init__(self, has_non_available_method: bool): self.has_non_available_method = has_non_available_method @restrict_if("has_non_available_method", error_cls=PermissionError) def some_method(self): return "方法正常执行" @restrict_if("has_non_available_method", error_msg="该功能已被禁用") def another_method(self): return "另一个方法正常执行"
测试效果:
# 允许访问的实例 obj_allow = NewClass(has_non_available_method=False) print(obj_allow.some_method()) # 输出:方法正常执行 # 禁止访问的实例 obj_deny = NewClass(has_non_available_method=True) obj_deny.some_method() # 抛出 PermissionError: 当前方法无访问权限
方案2:重写__getattribute__魔术方法(适合批量限制场景)
如果需要限制的方法数量多,可以统一维护限制列表,无需逐个加装饰器:
class NewClass: # 统一维护需要限制的方法名列表 _RESTRICTED_METHODS = {"some_method", "another_method"} def __init__(self, has_non_available_method: bool): self.has_non_available_method = has_non_available_method def __getattribute__(self, name: str): # 注意这里要用super调用避免无限递归 restrict_flag = super().__getattribute__("has_non_available_method") restricted_methods = super().__getattribute__("_RESTRICTED_METHODS") if restrict_flag and name in restricted_methods: raise PermissionError("当前方法无访问权限") return super().__getattribute__(name) def some_method(self): return "方法正常执行" def another_method(self): return "另一个方法正常执行" def free_method(self): return "不受限制的方法"
测试效果:
obj_deny = NewClass(has_non_available_method=True) print(obj_deny.free_method()) # 输出:不受限制的方法 obj_deny.some_method() # 抛出 PermissionError: 当前方法无访问权限
内容的提问来源于stack exchange,提问作者IO.PY
相关产品推荐
相关产品推荐

