应将外部依赖从父类__init__移至显式初始化方法、用组合替代继承封装依赖、通过抽象基类+工厂模式管理多环境依赖,并检查MRO中各父类的依赖策略一致性。

多层级类继承体系中,父类引入外部依赖(比如数据库连接、配置加载、第三方 SDK 初始化)时,容易造成子类无法独立实例化、测试困难、启动失败或循环依赖——这不是语法错误,而是设计层面的“死结”。核心在于:依赖不该由类定义阶段硬编码进继承链,而应解耦、延迟、可控。
把依赖从 __init__ 移到可选的初始化方法里
父类的 __init__ 不该直接调用高风险操作。把依赖加载逻辑拆出来,做成显式调用的方法,让子类决定何时、是否、如何触发。
- 父类只做声明和占位,不执行实际依赖初始化
- 提供类似 setup_resources() 或 connect_deps() 的方法,子类按需调用
- 在文档或类型注解中标明该方法的副作用和调用前提
用组合替代继承来承载依赖逻辑
如果某个父类的主要作用就是封装一组外部依赖(如日志客户端、缓存句柄、认证模块),那它本质上不是“类”,而是“组件”。把它抽成独立对象,通过属性注入给子类,而不是让子类继承它。
- 定义 DatabaseClient、ConfigLoader 等独立类,不带继承关系
- 子类通过 __init__(self, db_client=None, config=None) 接收实例
- 允许传入 mock 对象,彻底解决测试隔离问题
利用抽象基类 + 工厂模式控制依赖生命周期
当多个子类共用同一套依赖但初始化方式不同(例如不同环境用不同数据库 URL),用 ABC 定义契约,再用工厂函数/类统一管理实例创建,避免每个子类重复写 try-except 或环境判断。
- 定义 class DataProvider(ABC):,只声明 connect()、query() 等接口
- 实现 DevDataProvider、ProdDataProvider 等具体类
- 子类构造时接收一个 DataProvider 实例,而非自己 new 出来
检查 MRO 中所有父类是否都遵循相同依赖策略
多重继承时,只要有一个父类在 __init__ 里强行初始化依赖,整个链就可能卡住。运行时验证比静态阅读更可靠:
- 打印 Child.__mro__,逐个检查每个类的 __init__ 是否含阻塞式依赖调用
- 对可疑类,临时重写其 __init__,加 print(f"[DEBUG] {cls.__name__}.__init__ called") 定位源头
- 用 hasattr(obj, '_db_conn') 或 getattr(obj, 'client', None) is not None 判断依赖是否已就绪,而非假设它一定存在

















