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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 13:15:02