2012-08-16 94 views
2

我覺得這是對訪談最常見的問題:爲什麼不__del__正常工作

class A: 
    def __init__(self, name): 
      self.name = name 
    def __del__(self): 
      print self.name, 

aa = [A(str(i)) for i in range(3)] 
for a in aa: 
    del a 

所以這段代碼爲什麼什麼輸出。 輸出將是沒有,爲什麼? 那是因爲一個參考列表中的對象,然後我們調用del方法我們刪除這個參考但不是對象?

+1

誰會要求你在一次採訪中根據語言規範本身來描述一些有點模糊和無用的代碼,其行爲是不確定的還是未定義的?這些C或Java程序員是否試圖採訪Python職位? – 2012-08-16 17:39:37

+0

大聲笑,我得到這個問題大約3或4次)) – Denis 2012-08-16 17:52:54

回答

5

有至少2個引用a引用的對象(變量是引用對象,它們不是對象本身)。列表中有一個參考,然後是參考「a」。當你del a,你刪除一個引用(變量a),但不是列表中的引用。

還要注意的是Python並不保證__del__將永遠不會叫......

+2

無論如何不是多餘的'del a'?無論如何,對象'a'標籤的引用計數是否會在循環的下一次迭代時遞減? – 2012-08-16 15:50:26

+0

同意最後一點:作爲獨立程序運行OP代碼最終會在CPython 2.7.3下生成「2 1 0」,但在PyPy 1.9.1或Jython 2.5.1下生成* no *輸出,因爲__del__是從未打過電話 – DSM 2012-08-16 15:51:00

+1

@ sr2222大概是(除了列表中的最後一個元素) – mgilson 2012-08-16 15:51:18

4

__del__被當一個對象被銷燬調用;這會在從程序的可訪問內存中刪除最後一次可能的對象引用後發生。取決於實施情況,這可能會立即發生或可能在一段時間後發生。

您的代碼只是從執行範圍中刪除本地名稱a;該對象仍然在列表中,因此仍然可以訪問。例如,嘗試編寫del aa[0]

3

從文檔:

注德爾X不直接調用x.__del__() - 前遞減引用計數爲X個,而當X的引用計數爲零,後者只調用。

__del__當垃圾收集器發現要銷燬的對象時觸發。垃圾收集器將嘗試銷燬引用計數爲0的對象。del只是將本地名稱空間中的標籤分離,從而減少解釋器中對象的引用計數。垃圾收集器的行爲大部分被認爲是解釋器的實現細節,所以不能保證對象上的__del__將以任何特定的順序被調用,甚至根本不會被調用。這就是爲什麼這個代碼的行爲是未定義的。