2011-11-20 41 views
5
class ToBeDeleted: 
    def __init__(self, value): 
     self.value = val 

    # Whatever... 

    def __del__(self): 
     print self.value 

l = [ToBeDeleted(i) for i in range(3)] 
del l 

此打印2, 1, 0在列表中調用'del'


  • 現在,某處定義在規範中刪除的元素的順序,或者是其實現的具體情況? (或者我可能不瞭解底層機制)

  • 輸出是否可以是0, 1, 2我意識到2, 1, 0順序可能是爲了避免在刪除元素時重新分配內存,但仍然存在問題。

  • 而最後一個 - del ldel l[:]聲明有什麼區別?

+3

很懷疑到'__del __()調用的順序'的地方指定。甚至不要考慮嘗試編寫依賴於特定順序的代碼。 –

+0

即使指定了順序,也可以在任意位置持有對列表元素的引用,所以調用__del__方法的順序與從列表中移除引用的順序不同。 – millimoose

回答

8

運行del l將刪除該列表中的任何引用,所以符號將不復存在。相反,運行del l[:]將刪除列表中的內容,並將空白列表保留爲l

__del__方法是在最後一個實例引用被銷燬時運行的方法。

刪除的順序沒有指定,並且是特定於實現的。當您運行del l時,唯一保證的是列表l及其每個元素的引用計數將減少1。

With pypy,沒有別的事情會發生,直到垃圾收集器運行。刪除對象的順序取決於GC訪問對象的順序。

cpython,OP是正確的,觀察到引用遞減是從右到左發生的。當調用del l[:]時,這裏是用於減少refcounts的代碼:http://hg.python.org/cpython/file/2.7/Objects/listobject.c#l700。當調用del l,類似的代碼被用於遞減引用計數:http://hg.python.org/cpython/file/2.7/Objects/listobject.c#l596

+1

謝謝。但是,刪除元素的順序呢? –

1
  • 刪除次序是實現特定的。
  • 根據第一點的答案,是的,它可以以其他順序刪除它(甚至元素第一,隨機,不管),並避免重新分配與它沒有多大關係。這只是實施選擇如何走路的問題。如果釋放順序顛倒了分配順序,內存分配器可能會更快樂;但這只是一個猜測。
  • del l刪除變量本身(因此如果沒有其他東西持有它,則刪除列表),而del l[:]刪除列表中的所有元素。嘗試del l; print l
2

其他人已經回答。我將添加我在CPython源中找到的內容。

list_dealloc功能listobject.c文件中包含此評論立即遍歷列表項遞減其引用計數之前:

/* Do it backwards, for Christian Tismer. 
     There's a simple test case where somehow this reduces 
     thrashing when a *very* large list is created and 
     immediately deleted. */ 
+0

大發現!這也是相當有力的證據,表明刪除命令是未指定的,可能永遠不會。 – millimoose