15

是否有任何障礙妨礙weakref做所有__del__所做的一切,但有更強的保證(例如,finalize保證在解釋器退出之前進行調用,並且調用順序已定義良好等)?`weakref`回調可以代替`__del__`嗎?

看來,在遙遠的過去it was thoughtweakref最終將導致從語言中刪除__del__

是什麼阻止了這種情況發生?

似乎有few use cases for __del__,我知道所有的人似乎至少工作(通常好得多)與weakref回調或weakref.finalize

更新:

隨着PEP 442顯着提高的__del__的行爲,並與weakref由@gz和@ user2357112提到的關切,我想知道如果語言通常是朝着使__del__更可靠的移動,或對使用weakref而不是__del__或兩者。

+1

*「是什麼阻止了這種情況的發生?」*這是一個很*很少能夠回答的問題。我建議你在'python-list'上發佈這個文件,希望得到一些核心開發者的關注。 –

+2

Python的weakref支持非常糟糕,所以你不能將weakrefs引用到很多你想weakref的對象類型。這對你自己編寫的類型通常無關緊要,但是如果你的類型像'tuple'子類一樣,你不能弱化它。 – user2357112

+1

此外,weakref回調無法訪問指示對象,因此需要更仔細的設計。 – user2357112

回答

3

有一個有點務實的原因__del__仍然存在。幾個重要的改進weakref,包括finalize,分別是new in Python 3.4。所以,用更好的弱點代替__del__就錯過了用py3k改變語言的窗口。

我想大多數使用可以由基weakref功能所取代,但我這個觀察理查德奧德柯克在issue 15528襲擊,其中提出並實現finalize

[Weakref回調]低級別,並正確使用它們需要一些頭部劃痕。必須找到某處存儲weakref,直到指示對象死亡,並且不會意外地保留指示對象。然後必須確保回調釋放weakref(不留任何剩餘的ref-cycles)。

當它是一個選項,使用__del__方法是少得多的麻煩。

無論如何,也許這個問題應該在Python 4被考慮時再次提出? ;)

1

問題的答案是真的依賴於使用情況和也建議你考慮到不同的Python解釋器的實現沒有相同的GC行爲CPython的。

PyPy特別不呼叫__del__作爲-即將作爲對象是del -eleted或超出範圍,但「一段時間後」。因此,依賴於CPython的__del__行爲的代碼將在PyPy和其他替代解釋器上破解。

我推薦的是使用__enter____exit__以及with關鍵字。例如

from __future__ import print_function 

class MyClass(object): 

    def __enter__(self): 
     print("Entering") 

    def __exit__(self, exc_type, exc_val, exc_tb): 
     print("Exiting") 

# 'with MyClass()' can be used but want to show that 
# code in exit is executed regardless of object 
# life time 
obj = MyClass() 
with obj: 
    print("Stuff happening in between") 

結果是:

Entering 
Stuff happening in between 
Exiting 

陳述的上述順序保證,並且不依賴於GC行爲。

with塊中的代碼完成後應立即完成的事情可以在__exit__中進行,例如通常會放入析構函數中的東西 - 清除文件句柄,釋放鎖等等。

對象上的後續del或超出範圍將最終清除對象引用,這取決於解釋器的實現,但是應立即執行的事情最好不要依賴於該行爲。

相關問題