弱引用
弱引用
正是因为有引用,对象才会在内存中存在。
当对象的引用数量归零后,垃圾回收程序会把对象销毁。
但是,有时需要引用对象,而不让对象存在的时间超过所需时间。
这经常用在缓存中。
弱引用不会增加对象的引用数量。
引用的目标对象称为所指对象(referent)。
因此我们说,弱引用不会妨碍所指对象被当作垃圾回收。
弱引用在缓存应用中很有用,因为我们不想仅因为被缓存引用着而始终保存缓存对象。
如果对象存在,调用弱引用可以获取对象;否则返回 None。
弱引用是可调用的对象,返回的是被引用的对象;如果所指对象不存在了,返回 None。
WeakValueDictionary简介
WeakValueDictionary 类实现的是一种可变映射,里面的值是对象的弱引用。
被引用的对象在程序中的其他地方被当作垃圾回收后,对应的键会自动从 WeakValueDictionary 中删除。
因此,WeakValueDictionary 经常用于缓存。
临时变量引用了对象,这可能会导致该变量的存在时间比预期长。
通常,这对局部变量来说不是问题,因为它们在函数返回时会被销毁。
但是全局变量,除非显式删除,否则不会消失。
weakref 模块还提供了 WeakSet 类,按照文档的说明,这个类的作用很简单:“保存元素弱引用的集合类。元素没有强引用时,集合会把它删除。
”如果一个类需要知道所有实例,一种好的方案是创建一个WeakSet 类型的类属性,保存实例的引用。
如果使用常规的 set,实例永远不会被垃圾回收,因为类中有实例的强引用,而类存在的时间与Python 进程一样长,除非显式删除类。
弱引用的局限
不是每个 Python 对象都可以作为弱引用的目标(或称所指对象)。
基本的 list 和 dict 实例不能作为所指对象,但是它们的子类可以轻松地解决这个问题:
class MyList(list):
"""list的子类,实例可以作为弱引用的目标"""
a_list = MyList(range(10))
# a_list可以作为弱引用的目标
wref_to_a_list = weakref.ref(a_list)
set 实例可以作为所指对象。用户定义的类型也没问题。
但是,int 和 tuple 实例不能作为弱引用的目标,甚至它们的子类也不行。