第二章:数据结构-weakref:对象的非永久引用-缓存对象
2.8.5 缓存对象
ref和proxy类被认为是“底层”的。尽管它们对于维护单个对象的弱引用很有用,并且还支持对循环引用的垃圾回收,但WeakKeyDictionary和WeakValueDictionary类为创建多个对象的缓存提供了一个更适合的API.
WeakValueDictionary类使用它包含的值的弱引用,当其他代码不再真正使用这些值时,则允许垃圾回收。利用垃圾回收器的显示调用,下面展示了使用常规字典和WeakValueDictionary完成内存处理的区别:
import gc # gc模块是解释器垃圾回收器的接口。
from pprint import pprint
import weakref
gc.set_debug(gc.DEBUG_UNCOLLECTABLE)
class ExpensiveObject:
def __init__(self,name):
self.name = name
def __repr__(self):
return 'ExpensiveObject({})'.format(self.name)
def __del__(self):
print(' (Deleting {})'.format(self))
def demo(cache_factory):
# Hold objects so any weak references
# are not removed immediately.
all_refs = {}
# Create the cache using the factory.
print('CACHE TYPE:',cache_factory)
cache =cache_factory()
for name in ['one','two','three']:
o = ExpensiveObject(name)
cache[name] = o
all_refs[name] = o
del o # decref
print(' all_refs =',end=' ')
pprint(all_refs)
print('\n Before,cache contains:',list(cache.keys()))
for name,value in cache.items():
print(' {} = {}'.format(name,value))
del value # decref
# Remove all references to the objects except the cache.
print('\n Cleanup:')
del all_refs
gc.collect()
print('\n After,cache contains:',list(cache.keys()))
for name,value in cache.items():
print(' {} = {}'.format(name,value))
print(' demo returning')
demo(dict)
print()
demo(weakref.WeakValueDictionary)
如果循环变量指示所缓存的值,那么这些循环变量必须被显示清除,以使对象的引用数减少。否则,垃圾回收器不会删除这些对象,它们仍然会保留在缓存中。类似地,all_refs变量用来保存引用,以防止它们被过早地垃圾回收。
运行结果: