如果循環中的對象沒有自定義的__del__
方法,則不必擔心引用週期,因爲Python可以(也將)以任何順序銷燬對象。
如果你的自定義方法確實有一個__del__
方法,Python不知道是否有一個對象的刪除會影響另一個對象的刪除。說一個對象被刪除時,它會設置一些全局變量。所以,這些物體粘在一起。作爲一個快速測試,你可以做一個__del__
方法,打印的東西:
class Deletor(str):
def __del__(self):
print(self, 'has been deleted')
a = Deletor('a') # refcount: 1
del a # refcount: 0
輸出:
a has been deleted
但是,如果你有這樣的代碼:
a = Deletor('a') # refcount: 1
a.circular = a # refcount: 2
del a # refcount: 1
它什麼也不輸出,因爲Python不能安全地刪除a
。
有兩種解決方案。該weakref
:
# refcount: a b
a = Deletor('a') # 1 0
b = Deletor('b') # 1 1
b.a = a # 2 1
a.b = weakref.ref(b) # 2 1
del a # 1 1
del b # 1 0
# del b kills b.a # 0 0
輸出:
b has been deleted
a has been deleted
(注意:第一是如何b
刪除,它可以刪除a
前)
你也可以手動刪除週期(如果你可以跟蹤他們):
# refcount a b
a = Deletor('a') # 1 0
b = Deletor('b') # 1 1
b.a = a # 2 1
a.b = b # 2 2
del b # 2 1
print('del b')
del a.b # 2 0
# b is deleted, now dead
# b.a now dead # 1 0
print('del a.b')
del a # 0 0
print('del a')
輸出S:
del b
b has been deleted
del a.b
a has been deleted
del a
注意b
如何後a.b
刪除被刪除。