Python单例Config类实现失败:递归错误成因咨询
问题分析与修复
问题描述
尝试为配置类实现单例模式:_Config类负责加载config.yaml文件,Config作为其子类,预期每次实例化返回唯一实例。但执行config1 = Config()时触发RecursionError(递归深度超限)。
错误根源
递归的核心原因是Config.__init__中的hasattr(self, '_config')调用,结合_Config.__getattr__的实现形成了无限循环:
- 第一次实例化
Config时,__init__先检查hasattr(self, '_config'),此时_config还未被初始化(super().__init__()尚未执行); hasattr会尝试获取self._config,由于_Config重写了__getattr__方法,且此时实例的_config属性不存在,会触发__getattr__;- 在
__getattr__中,当name == '_config'时,代码返回self._config,这又会再次触发__getattr__(属性仍未初始化),形成无限递归。
代码问题点
_Config.__getattr__处理_config属性时,直接使用self._config会触发自身调用;Config.__init__用hasattr检查属性,会间接触发__getattr__,而此时_config还未完成初始化。
修复方案
方案1:修改属性检查逻辑
用直接检查实例__dict__的方式替代hasattr,避免触发__getattr__:
def __init__(self): if '_config' not in self.__dict__: logger.debug('no _config') super().__init__()
方案2:修复__getattr__的递归问题
当访问_config时,用object.__getattribute__直接获取属性,绕过__getattr__的递归调用:
def __getattr__(self, name): if name == '_config': return object.__getattribute__(self, '_config') if name not in self._config: raise AttributeError(name) item = self._config.get(name) if item is None: raise NotImplementedError(f'"{name}" not found in config.yaml') if isinstance(item, dict): item = _Config(config=item) return item
方案3:简化单例实现
直接在__new__中完成初始化,避免__init__重复执行:
class Config(_Config): _instance = None def __new__(cls): if cls._instance is None: logger.debug('Creating a new Config instance') cls._instance = super().__new__(cls) super(Config, cls._instance).__init__() return cls._instance def __init__(self): # 空实现防止多次初始化 pass
验证修复
修改后执行config1 = Config(),将不再触发递归错误,且每次实例化都会返回同一个单例对象。
内容的提问来源于stack exchange,提问作者CyberPlayerOne
相关产品推荐
相关产品推荐

