功能說明
Python使用引用計數、分代算法回收垃圾,引用計數操作方法:
- 對象被引用一次,其計數器+1
- 對象被
del
,其計數器-1 - 對象的引用計數為0時候會被回收
python的魔法方法__del__
,類似java的finalize
方法,會在對象被回收時執行。
實驗驗證
實驗1: 刪除僅引用一次的對象
步驟:
- 創建一個class,重寫
__del__
方法,打印信息 - 創建該類實例,然后把它del掉,觀察是否有回收消息
預期:
對象被回收。
驗證代碼:
import time
class A:
def __del__(self):
print("A instance deleted")
a = A()
del a
time.sleep(3)
print("sleep end")
print(a)
輸出結果:
A instance deleted
sleep end
Traceback (most recent call last):
File "/Users/wuhf/PycharmProjects/cookdata/cookdata/__init__.py", line 16, in <module>
print(a)
NameError: name 'a' is not defined
結果分析:
- 調完del命令,
__del__
方法被執行,對象立即被刪除(引用次數為0) - 調完del命令后引用
a
被刪除(其引用的對象不一定被刪除,但是引用一定被刪除)
實驗2: 刪除被多次引用的對象
步驟:
- 在上面那個用例的基礎上,用多個引用引用A的對象
- 刪除其中一個引用,觀察對象是否被刪除
預期:
刪除一個引用,只是那個引用被刪除了,但是對象不會被刪除。
驗證代碼:
import time
class A:
def __del__(self):
print("A instance deleted")
a = A()
b=a
c=a
del a
time.sleep(3)
print("sleep end")
print("b=%s" % str(b))
print("c=%s" % str(c))
try:
print("a=%s" % str(a))
except Exception as e:
print(e)
輸出結果:
sleep end
b=<__main__.A object at 0x101c154d0>
c=<__main__.A object at 0x101c154d0>
name 'a' is not defined
A instance deleted
結果分析:
- 調完del命令刪除a后,對象並沒有被刪除,通過其他引用b和c可以繼續訪問
- 對象在進程結束前被回收了,實際上不調用任何del,進程退出前A的實例都會被回收
- 推論:如果想回收A的實例,需要刪除所有它的引用(引用次數降到0)
以上驗證基於Python 3.7.7