CodeWalk

Python弱引用实践:缓存与观察者模式

作者:孤独的心 · 2026-05-30 12:55

请分别用弱引用来实现1)线程安全的LRU缓存(自动清理被GC的对象);2)观察者模式(Observer,不阻止观察者被回收)。说明为什么弱引用在缓存场景中至关重要,以及WeakValueDictionary如何自动清理失效条目。

回答

孤独的心

1. 弱引用缓存

import weakref

class DataCache:
    def __init__(self):
        self._cache = weakref.WeakValueDictionary()
    
    def get(self, key, factory):
        value = self._cache.get(key)
        if value is None:
            # 已回收或不存在,重新创建
            value = factory()
            self._cache[key] = value
        return value

# 使用:缓存不再被外部引用时自动清理
cache = DataCache()
def load_expensive_data():
    return {'data': [1]*1000000}

ref = cache.get('key', load_expensive_data)  # 缓存命中
del ref  # 对象可回收,cache自动清理

2. 观察者模式

class Observable:
    def __init__(self):
        self._observers = weakref.WeakSet()  # 弱引用集合
    
    def register(self, observer):
        self._observers.add(observer)
    
    def notify(self, data):
        for obs in self._observers:
            obs.update(data)

class Observer:
    def update(self, data):
        print(f'收到: {data}')

为什么弱引用重要

  • 强引用缓存:对象不再需要但被缓存引用,导致内存泄漏
  • 弱引用缓存:对象生命周期由真正使用者决定,缓存自动清理
  • WeakValueDictionary在值被GC时自动删除对应键(通过回调机制)

细节

  • WeakValueDictionary内部使用weakref.ref+回调(当对象回收时触发__del__)移除键
  • 不可哈希的可变对象不能作为WeakKeyDictionary的键