遇到了python關於del的小問題,又引發了一些問題,就簡單的記錄下,如果有不同意見,歡迎一起討論~
python類似java是有記憶體回收機制的語言,所以我們不需要像c++一樣通過解構函式來手動釋放記憶體,
但是python也同樣提供了__del__釋放方法。當一個對象的引用計數為0時,會被自動調用,那麼先來說說
引用計數吧。
1.引用計數
#!/usr/bin/env python
#coding:UTF-8import sysclass MyClass(object): def __init__(self): print('i am __init__ function') def __del__(self): print('i am __del__ function')if __name__ == '__main__': m1 = MyClass() m2 = m1 print(sys.getrefcount(m1))
結果如下圖:
結果很讓人吃驚吧,只有兩個執行個體,為什麼引用計數是3 ?
都知道python是一門指令碼語言,解釋型語言,但是不知道大家有沒有注意python其實也是有編譯過程的。
.pyc檔案就是個很好的證明。可以去/usr/lib/python看看
所以說的細緻一點python是一門先編譯後解釋的語言,編譯指的是編譯成為位元組碼,然後然逐行解釋位元組碼。
平時解譯器幫我們做好了而已,你可能會說上面的代碼怎麼看不見.pyc檔案呢,你把函數單獨成一個.py檔案
然後import匯入後編譯就可以看見了。其實.pyc檔案只是編譯後的 PyCodeObject儲存在硬碟上的表現而已。
編譯產生的真正的結果是PyCodeObject
過程.py ->編譯 -> PyCodeObject ->解釋(虛擬機器執行)
現在說引用計數,繞了個彎,其實也不算,因為引用計數的值不對就是因為python的編譯過程。
詳情可參考http://blog.csdn.net/balabalamerobert/article/details/1649490
2.__del__
前面說了python的引用計數為0時會自動回收對象,所以一般是不推薦我們使用python中的__del__刪除方法的
我在自己使用__del__過程中就遇到了一個問題,還是看代碼:
定義了兩個類,一個基類MyClass有名字和電話等資訊,衍生類別DerClass添加了地址,每個類都有一個attribute屬性
glb和der_glb。
#!/usr/bin/env python#coding:UTF-8class MyClass(object): glb = 100 #global variable def __init__(self, nm, ph): self.name = nm self.phone = phclass DerClass(MyClass): der_glb = 200 #global variable def __init__(self, nm, ph, addr): super.__init__(nm, ph) #python3 self.address = addr def __del__(self): #del self.__class__.der_glb del self.der_glb print 'del der_glb'if __name__ == '__main__': m1 = MyClass('wwh', '123') m2 = DerClass('wwh', '456', 'xian')
主要看下del函數,我在del函數中自己調用了del self.der_glb來刪除這個所有類共用的變數
(python中類內定義的變數所有執行個體共用)
結果報錯了
但是我改為del self.__class__.der_glb卻正確了
這是什麼原因呢
前面說了python中類內定義的變數所有執行個體共用,那麼每個執行個體在結束後也就是自己的引用計數為0時都會被調用del
也就是說每個執行個體都del了一遍只有一份的der_glb變數,當然是不對的
那麼為什麼加上__class__就正確了呢
python的記憶體模型應該是我們定義了一個類後,這個類的模板module也會在記憶體中儲存一份(id(Der_class)可證明),畢竟它還有所有執行個體需要用的變數等等。
所以__class__含義應該是擷取到記憶體中這個module的地址,然後取得module的der_glb,刪除它。
刪除它後我們當然不能使用它了。
類似python的delattr(obj, attr)刪除類的屬性一樣
在我按照上面所說的進行修改後,del self.__class__.der_glb,運行成功,並且再次定義類的執行個體時訪問der_glb屬性報錯,報錯結果如下:
可見在del der_glb後,再次使用der_glb顯示has no attibute 'der_glb',證明前面我所說的是正確的,該屬性已經被刪除
說明一下python中的der_glb類似c++中的static變數,所有執行個體被共用,但是在python中被稱為該類的屬性attribute。
雖然python很好用,但是也需要搞清楚一些原理 ^_^