weakvaluedictionary和weakkeydictionary可自动清理缓存:前者值为弱引用,对象无强引用时自动删除条目;后者键为弱引用,对象销毁时连带清除对应状态;weakref.ref适用于单对象回调场景,但需手动判空且须消除隐式强引用。

用 WeakValueDictionary 或 WeakKeyDictionary 替代普通字典,是解决缓存溢出最直接有效的方式——只要缓存项不再被其他地方强引用,它就会自动从字典中消失,根本不需要你手动清理。
缓存对象生命周期不受控?用 WeakValueDictionary 存值
当你按 ID、名称或其他键缓存「可被外部丢弃」的对象(比如 GUI 控件、ORM 实例、解析后的 XML 节点),且希望它们在没人再用时立刻释放,WeakValueDictionary 是首选。
- 值是弱引用:只要缓存里的对象(如
node)没了其他强引用,GC 一回收,对应条目自动从字典里删掉 - 键仍是强引用:所以你要确保键本身不长期持有不该持有的东西(比如别用大字典当键)
- 不能用不可弱引用类型作值:例如某些 C 扩展类、内置类型如
int或str通常不可弱引用,调用会抛TypeError: cannot create weak reference to 'int' object - 示例:
import weakref _node_cache = weakref.WeakValueDictionary() <p>def get_node_by_id(node_id): if node_id not in _node_cache: _node_cache[node_id] = load_node_from_db(node_id) # 返回一个可弱引用的实例 return _node_cache[node_id] # 可能返回 None,建议加判空 </p>
以对象为索引存状态?用 WeakKeyDictionary 存键
当你想为某个对象(比如 socket、Widget 实例)缓存它的渲染状态、配置或临时数据,又不希望这个缓存阻止对象被回收,就该让「对象」当键,而不是当值。
- 键是弱引用:一旦那个
Widget实例被del或离开作用域,它在字典里的整个条目(包括你的状态数据)就自动消失 - 值是强引用:所以你存的
dict、list等不会因字典存在而被拖住 - 键必须可哈希且可弱引用:
list、dict不行,会报TypeError: unhashable type;自定义类默认可哈希,但若重写了__hash__或__eq__且逻辑不当,也可能失效 - 遍历时注意安全:迭代中可能有键被回收,导致
RuntimeError: dictionary changed size during iteration,应写成for k, v in list(cache.items()):
单个对象要缓存快照?用 weakref.ref + 显式判空
不是所有缓存都适合字典结构。比如你在回调里需要访问 self,但又怕 timer 持有它导致 widget 无法释放,这时 weakref.ref 更灵活。
- 它返回一个 callable,必须先调用才能取对象:
obj_ref = weakref.ref(obj); real_obj = obj_ref() - 调用后可能返回
None:绝不能直接写obj_ref.some_method(),那会报AttributeError - 别把它塞进全局 dict:比如
GLOBAL_CACHE["timer"] = obj_ref,这会让弱引用永远活在模块级变量里,失去意义 - 错误示范:
self._timer = threading.Timer(1.0, lambda: self.on_timeout()) # 强引用 self
正确写法:self._weak_self = weakref.ref(self) self._timer = threading.Timer(1.0, lambda: self._on_timeout_safe()) <p>def _on_timeout_safe(self): obj = self._weak_self() if obj is not None: obj.on_timeout() </p>
最容易被忽略的是:weakref 不是“设了就完事”的开关。它只在对象**确实没有其他强引用**时才起效。如果你的缓存对象还被 logging、pytest fixture、asyncio task、或 Qt 信号槽(未指定 Qt.WeakConnection)强持有着,weakref 就形同虚设——得先排查这些隐式强引用路径。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











