Python单例类继承父类时运行无栈追踪直接失败问题排查
问题排查思路
- 优先排查无限递归场景:Python默认递归深度限制约为1000,超出后会触发栈溢出直接终止程序,部分底层调用场景下不会输出完整栈追踪。你可以在getter、setter内部增加计数打印逻辑,快速验证是否出现循环调用。
- 定位property调用逻辑:Python的property会接管所有同名属性的读写操作,所有
self.x的访问都会触发对应的getter/setter方法,优先检查存取方法内部是否直接访问了同名property。 - 验证修复逻辑:修改存储属性名后再次运行,确认实例化、属性读写逻辑均符合预期。
问题根源
类B中定义的x property的存取方法存在经典的无限递归问题:
- getter方法中
return self.x会再次触发x的getter,形成无限循环 - setter方法中
self.x = x + 1会再次触发x的setter,形成无限循环
程序运行后快速耗尽递归深度,触发栈溢出直接退出,因此没有栈追踪输出。
解决方案
将实际存储属性值的变量名和property名区分开,通常用单下划线前缀作为内部存储属性的命名规范,修改后代码如下:
class B: @property def x(self): print('x getter') # 访问内部存储的属性,不会触发property return self._x @x.setter def x(self, x) -> None: print('x setter') # 写入内部存储的属性,不会触发property self._x = x + 1 class A(B): __instance = None # __new__是类方法,第一个参数惯例用cls表示类对象,原写法self也可运行但不符合规范 def __new__(cls): ''' Virtually private constructor ''' if not A.__instance: A.__instance = object.__new__(cls) A.__instance.__setup() return A.__instance def __setup(self): self.x = 10 def minus(self): self.x -= 3 a1 = A()
修改后运行程序会正常输出x setter,实例化完成后a1.x的取值为11,符合setter中x+1的逻辑。
内容的提问来源于stack exchange,提问作者Alex F
相关产品推荐
相关产品推荐

