Python弱引用实践:缓存与观察者模式
请分别用弱引用来实现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的键