正是因为有引用,对象才会在内存中存在。当对象的引用数量归零后,垃圾回收程序会把对象销毁。
弱引用不会增加对象的引用数量,引用的目标对象称为所指对象(referent)。常作缓存使用。
一般我门会使用weakref包的集合(WeakKeyDictionary, WeakValueDictionary, WeakSet)和finalize,一般低层接口weakref.ref我门不建议使用。
WeakKeyDictionary 是一种可变映射,值是对象里面的弱引用。
class Cheese: def __init__(self, kind): self.kind = kind def __repr__(self): return 'Cheese(%r)' % self.kind import weakref stock = weakref.WeakValueDictionary() catalog = [Cheese('Red Lercier'), Cheese('Tielet'), Cheese('Brei'), Cheese('Pramene')] for cheese in catalog: stock[cheese.kind] = cheese print(sorted(stock.keys())) # ['Brei', 'Pramene', 'Red Lercier', 'Tielet'] del catalog print(sorted(stock.keys())) # ['Pramene'] 确实由于删除了catalog,大部分内容没有了del cheese # cheese这里是全局变量 是最后引用 print(sorted(stock.keys())) # []
WeakKeyDictionary 可以为应用中的其他部分拥有的对象附加数据,这样就无需为对象添加属性。这对覆盖属性访问权限的对象尤其有用。
WeakSet 可以保存元素的弱引用集合类。元素没有强引用时,集合会把它删除。如果需要维护所有实例状态的类,好的方案就是创建WeakSet类型属性,保存实例的引用。
弱引用的局限
基本的list和dict实例不能作为所指对象,但它们的子类可以轻松的解决这个问题。int和tuple实例不能作为弱引用目标,甚至子类也不行,原因是基于CPython的实现细节。