面试题答案
一键面试实际应用场景
- 缓存系统:在缓存中,我们希望当内存紧张时,缓存中的对象能被垃圾回收,释放内存。若使用强引用,缓存对象即使长时间未被使用,只要缓存存在,对象就不会被回收。而弱引用可解决此问题,它不会阻止对象被回收。例如,一个Web应用的页面缓存,当内存不足时,使用弱引用的缓存页面可被垃圾回收,避免内存占用过多。
- 事件监听机制:在事件监听场景中,若监听器对被监听对象使用强引用,可能导致被监听对象即使不再被其他地方使用,也无法被回收,因为监听器持有强引用。使用弱引用,当被监听对象不再被其他地方引用时,垃圾回收器可正常回收它,而监听器在对象被回收后会自动变为
None
。
避免循环引用问题
假设有两个类 A
和 B
,它们相互引用形成循环引用:
import weakref
class A:
def __init__(self):
self.b = None
class B:
def __init__(self, a):
self.a = weakref.ref(a)
a = A()
b = B(a)
a.b = b
在上述代码中,A
类的实例 a
持有 B
类实例 b
的强引用,B
类实例 b
通过弱引用持有 A
类实例 a
。这样当外部没有对 a
的强引用时,垃圾回收器可以回收 a
,之后 b.a
会变为 None
,从而打破循环引用。若 b
此时也没有其他强引用,也会被垃圾回收。
# 取消对a的外部强引用
a = None
此时,若没有其他对 a
实例的强引用,a
实例会被垃圾回收,b.a
变为 None
,避免了循环引用导致的内存泄漏。