2009-07-10 60 views
7

我一直在想如何在Python中編寫類。更具體地說,構造函數是如何實現的以及如何銷燬對象。我不想依靠CPython的引用計數來進行對象清理。這基本上告訴我,我應該使用語句來管理我的對象生命週期,並且我需要一個明確的close/dispose方法(如果對象也是上下文管理器,則可以從__exit__調用此方法)。在__del__中執行對象關閉/配置真的可以嗎?

class Foo(object): 
    def __init__(self): 
     pass 
    def close(self): 
     pass 

現在,如果我的所有對象的行爲以這種方式和我所有的代碼陳述或顯式調用用來close()(或dispose())我並不真的認爲有必要對我來說,把任何代碼__del__。我們真的應該使用__del__來處理我們的物品嗎?

+2

我不想依靠CPython的引用計數來做對象清理。爲什麼不是?對象引用計數有什麼問題? – 2009-07-10 21:35:31

+0

@ S.Lott,如果您將代碼移動到具有更高級垃圾收集的環境(例如Jython或IronPython),那麼引用計數就不存在了 - 如果有一天CPython(例如通過Unladen Swallow)被拖拽和尖叫進入21世紀呢?我同意OP關於我的可重用便攜庫中的「不依賴」RC的觀點(與一次性使用,丟棄,腳本和次要模塊相對)。 – 2009-07-11 02:51:14

+0

@ S.Lott:Alex已經回答了你的問題。想要不依賴於引用計數的另一個好理由是來自PyPy項目的JIT。與CPython相比,它背後的人似乎樂觀地認爲它能夠提供更高的速度。 – Arlaharen 2009-07-12 09:58:50

回答

13

簡短的回答:第

龍答:使用__del__是棘手,主要是因爲它不能保證被調用。這意味着你不能在那裏做那些絕對必須完成的事情。這反過來意味着__del__基本上只能用於遲早會發生的清理,比如清理當進程退出時將清理的資源,所以__del__不會被調用並不重要。當然,這些也是Python爲你做的一樣的事情。所以有點讓__del__沒用。

另外,__del__在Python垃圾收集時被調用,並且您不希望等待Pythons垃圾收集,這意味着無論如何您都不能使用__del__。因此,請不要使用__del__。改爲使用__enter__/__exit__

FYI:這裏是一個非圓形情況的例子,其中的析構函數沒有被調用:

class A(object): 
    def __init__(self): 
     print('Constructing A') 

    def __del__(self): 
     print('Destructing A') 

class B(object): 
    a = A() 

OK,所以這是一個類屬性。顯然這是一個特例。但它只是表明,確保__del__被調用並不簡單。我很確定我看到更多的非循環情況,其中__del__未被調用。

0

如果你確信你不會進入循環引用,然後以這種方式使用__del__是OK:儘快當引用計數變爲零時,CPython VM將調用該方法並銷燬該對象。

如果您打算使用循環引用 - 請仔細考慮,並檢查弱引用是否有幫助;在很多情況下,循環引用是不良設計的首要症狀。

如果您無法控制您的物體將被使用的方式,那麼使用__del__可能並不安全。

如果您打算使用JPython或IronPython,則__del__根本就不可靠,因爲垃圾回收會導致最終的對象銷燬,而這是您無法控制的。

總之,在我看來,__del__通常是非常安全和良好的;然而,在很多情況下,退一步可能會更好,並嘗試從不同的角度來看問題; try/except和context的一個很好的用法可能是更爲pythonic的解決方案。

相關問題