python是基于引用计数的垃圾回收机制,引用计数就涉及到循环引用这种麻烦的场景。简单代码如下:
class A:
def __init__(self):
self.b = B(self)
def __del__(self):
print('des A')
class B:
def __init__(self, a):
self.a = a
def __del__(self):
print('des B')
当创建a = A()之后,无论是del a 还是 a = None,两条析构的输出都不会马上打印出来,而是过一会,由python自行检测出有循环引用的垃圾没有回收,此时才回收,才会打印出两条日志输出。
此种典型情况,尽管可以交由python自行检测,但是考虑到性能和内存利用率,就特别需要弱引用来帮助降低垃圾回收的成本。可以改A:
class A:
def __init__(self):
self.b = B(weakref.ref(self))
def __del__(self):
print('des A')
也可以改B:
class B:
def __init__(self, a):
self.a = weakref.ref(a)
def __del__(self):
print('des B')
如果B永远是A的寄生类,那两种改法都ok,但是如果B有其他用处,比如:
class C:
def __del__(self):
print('des C')
>>> c = C()
>>> b = B(c)
>>> del c
>>> print(b.a) ### dead ref
就会出现死引用。实际使用依情况而定。