访问Python对象的__dict__为何会引发内存回收延迟?
访问__dict__影响Python实例GC回收时机的原因解析
1. __dict__是延迟构造的
Python 3.12中,新式类实例的__dict__采用延迟初始化:只有当你第一次显式访问__dict__(如foo.__dict__)时,解释器才会为实例创建并初始化这个字典。这是内存优化手段,避免为不需要动态添加属性的实例额外分配字典内存。
2. 带__del__的循环引用GC处理逻辑
Python GC处理循环引用时,若对象定义了__del__方法,会分两步处理:
- 第一次调用
gc.collect():将这类循环引用对象标记为不可达(unreachable),但不会立即执行__del__或销毁对象——因为__del__可能重新引用对象使其“复活”,GC需先确认无外部引用。 - 第二次调用
gc.collect():再次检查不可达对象,确认无外部引用后,执行__del__并销毁对象。
3. 访问__dict__触发回收延迟的原因
你的代码中,lru_cache装饰的self._bar会持有实例引用,形成实例 → self.bar → 实例的循环引用:
- 未访问__dict__时:实例的
__dict__未创建,循环引用结构简单。此时GC在第一次收集时即可识别实例无外部引用,直接完成回收(和Python对未初始化__dict__实例的特殊处理有关)。 - 访问__dict__后:
__dict__被创建,循环引用结构变为实例 → __dict__ → self.bar → 实例。额外的__dict__引用让GC第一次收集时无法直接确认对象可安全销毁,将其放入不可达队列,需第二次gc.collect()才能执行__del__并销毁实例。
官方文档参考方向
- 数据模型章节:查找“instance dict”相关内容,了解延迟初始化的设计说明。
- 垃圾回收章节:查找“cyclic references with del”相关内容,明确带析构方法的对象回收流程。
内容的提问来源于stack exchange,提问作者joudan
相关产品推荐
相关产品推荐

