2015-02-10 46 views
2

當測試一個持有弱引用的類時,我偶然發現了一個稍微奇怪的行爲:Python垃圾回收器似乎缺少列表中的最後一個元素。一個最小的例子:垃圾回收器缺少列表中的最後一個值

class Test(object): 

    def __init__(self, i): 
     self.i = i 

    def __del__(self): 
     print('Deleting Test {0}'.format(self.i)) 

if __name__ == '__main__': 

    x = [Test(i) for i in range(5)] 
    for t in x: 
     print(t.i) 
    x = [] 

上面將打印:

刪除試驗3

刪除試驗2

刪除試驗1

刪除試驗0

這發生任何創建的對象(10,100,1000的列表的大小,等等)。爲了仔細檢查是否屬於這種情況,我試圖強制垃圾收集,並確保在將原始列表設置爲[]或調用後仍然可以使用對原始列表值的弱引用(並且未標記爲已死) del x

import weakref 
import gc 

z = None 

if __name__ == '__main__': 
    x = [Test(i) for i in range(5)] 
    for t in x: 
     print(t.i) 

    z = weakref.ref(x[4]) 
    x = [] 
    gc.collect(2) 
    print(z().i) 

此外,試圖建立一個大名單(再次)力垃圾收集什麼都不做;例如,在插入上述x = []gc.collect(2)之間的以下:

p = [i for i in range(10000000)] 

這發生在兩個Python的2.7.6和3.3.3。我意識到垃圾收集是非確定性的,但這似乎相當可疑。是否有一個特定的原因,最後一個元素沒有被垃圾收集,或者這是一種錯誤的錯誤?

+0

奇怪。我運行了你的代碼,最後一行是'Deleting Test 4'。 Python 2.7和3.4都有相同的輸出。運行Debian測試。 – 2015-02-10 10:12:41

+0

@BasicWolf是的,它仍然顯示GC正在追蹤它 - 當解釋器關閉時它確實在最後收集它。 – Yuushi 2015-02-10 10:14:35

回答

5

您的第一個源代碼中的變量t仍然存在並保存對最後一個條目的引用。在您致電del t後最後Test對象將被刪除。

+1

嘿,當然 - 我覺得這麼愚蠢。謝謝。 – Yuushi 2015-02-10 10:16:50