2015-10-06 41 views
0

我只是想知道我的理解https://docs.python.org/2/extending/extending.html#reference-counts權:循環引用和垃圾回收在Python

我有一個(出於某些目的必須有相互參考)兩大類:

class Foo(object): 
    def __init__(self, child): 
     self._child = child 
     self._child.parent = self 
    @property 
    def child(self) 
     return self._child 
    @child.setter 
    def child(self, value): 
     #Optional to delete reference to parent 
     ''' 
     self._child.parent = None 
     ''' 
     self._child = value 
     self._child.parent = self 

class Child(object): 
    @property 
    def parent(self): 
     return self._parent 
    @parent.setter 
    def parent(self, value) 
     self._parent = value 

在設置新的孩子之前,我是否需要製作self._child.parent = None,以便老孩子可以被垃圾清理?我被上面的鏈接引用嚇倒了,這種情況是我不確定的。直到現在我發現的所有東西都描述了兩個元素被刪除並且有一個指向對方的情況。

+0

請注意,這裏使用'property'是完全多餘的,不需要。只需使用'self.child'和'self.parent屬性即可。這當然不是Java中使用getter和setter的地方,如果需要的話,您可以隨時切換到使用屬性(例如,在設置或獲取時需要執行額外的處理)。 –

+0

我知道,實際上在嘗試設置時有很多'setter'邏輯 - 我只是跳過所有這些以獲得更清晰的示例。 – MSeifert

+0

雖然在這裏的'child.setter'屬性中可能會添加'self._child.parent = self'。 –

回答

1

在這種情況下,您不必設置self._child.parent = None,否。您已經通過將對子對象的父引用設置爲其他內容來打破這個圈子。

當參考子對象消失時,圓形被打破,對象可以被正常的引用計數機制刪除;它沒有關係,它本身仍然有傳出引用。

即使存在循環引用,垃圾收集器也會通過中斷圓中的某個引用來處理該圓。唯一的情況是,如果圓圈中的一個對象具有自定義方法__del__

+0

好吧,這是有道理的。我實際上並不確定,因爲我使用大數組作爲孩子嘗試了它,並且沒有刪除引用給孩子的記憶(好吧,我只是看了任務管理器)沒有減少幾秒鐘,而刪除孩子指針父母的內存幾乎立即釋放。但這可能是一些只是因爲gc是由於某些原因,我無法複製它 – MSeifert

+0

@MSeifert:您的操作系統將不會立即回收釋放的內存,除非在其他地方對該內存有迫切的需求。程序釋放舊內存並始終分配新內存;操作系統分配因此,即使內存數量已經釋放,程序的內存也可以保持穩定。 –

+0

@MSeifert:同樣,在任務管理器中觀察內存分配呃是一種監視內存問題的非常不可靠的方法。 –