自定义@property装饰器递归错误修复:不修改属性且保留实例访问
修复@property与__getattr__的递归错误问题
问题原因分析
调用y.var时,Y类的var属性将上下文切换为x实例,随后访问x.var;但X类本身没有var属性,会触发__getattr__方法去调用getattr(y, 'var'),形成y.var → x.var → y.var的无限循环,最终触发RecursionError。
修复方案(不修改Y的var属性、保留X对y的访问权限)
修改X类的__getattr__方法,加入递归调用检测,在发现循环依赖时抛出明确错误,避免栈溢出:
import inspect class X(object): def __getattr__(self, name): # 遍历调用栈,检测是否存在重复的属性获取操作 for frame in inspect.stack()[1:]: if frame.function == '__getattr__' and frame.locals.get('name') == name: raise RuntimeError(f"循环引用错误:无法获取属性 '{name}',X与Y实例的属性形成递归依赖") return getattr(y, name) class Y(object): @property def var(self): self = x # 保留原有逻辑不修改 return self.var x, y = X(), Y() print(y.var) # 输出:RuntimeError: 循环引用错误:无法获取属性 'var',X与Y实例的属性形成递归依赖
补充说明
你提到这种递归本质上和Y类属性直接返回自身的情况等价,属于逻辑层面的正常错误。如果不想引入调用栈检测,也可以针对特定属性做判断,但上述方案更通用,既能保留X对y的其他属性访问权限,又能在出现循环时给出清晰的错误提示,替代模糊的栈溢出错误。
内容的提问来源于stack exchange,提问作者Marcin Tamiński
相关产品推荐
相关产品推荐

