2016-07-21 88 views
1

我正在寫一個函數,它需要一個很大的參數,並且運行很長時間。它只需要一半的論據。如果沒有更多引用指向該函數,函數是否可以刪除該參數指向的值?如何儘早刪除函數參數?

我能得到它,將會刪除該函數返回,就像這樣:

def f(m): 
    print 'S1' 
    m = None 
    #__import__('gc').collect() # Uncommenting this doesn't help. 
    print 'S2' 
class M(object): 
    def __del__(self): 
    print '__del__' 
f(M()) 

此打印:

S1 
S2 
__del__ 

我需要:

S1 
__del__ 
S2 

我也嘗試def f(*args):def f(**kwargs),但它沒有幫助,我仍然得到__del__最後。

請注意,我的代碼依賴於Python具有引用計數的事實,並且只要對象的引用計數降至零,就會調用__del__。我希望函數中間的函數參數drop的引用計數爲零。這可能嗎?

請注意,我知道的一種解決方法:傳遞的參數列表:

def f(ms): 
    print 'S1' 
    del ms[:] 
    print 'S2' 
class M(object): 
    def __del__(self): 
    print '__del__' 
f([M()]) 

此打印:

S1 
__del__ 
S2 

有沒有辦法讓早期的缺失不改變API(例如在參數中引入列表)?

如果它是很難得到一個便攜的解決方案在許多Python實現的作品,我需要一些東西,在最近的CPython 2.7工作。它不需要記錄。

+2

你爲什麼要這麼做?一般來說,我認爲python不會在引用計數達到0時立即收集某些內容,但只有一些(未定義)時間。你應該能夠強制垃圾收集。 – syntonym

+1

參數從調用者的範圍傳入。最終,對象仍然在那裏引用。然而,如果你的函數中的ref數量很少,直到你的函數結束,那麼這個對象可能不會被垃圾回收,因爲父類的作用域的引用還沒有被清理。 - 這在很大程度上只是一個猜測,但我不知道'foo(m)'和'foo(M())'之間的行爲會有什麼不同。邏輯決定它*不應該*不同,但是這也取決於實現。 – deceze

+0

我*要*說,即使您解除了參數,它仍然存在於函數範圍之外。 –

回答

0

它看起來像它不可能做的CPython 2.7早期缺失而不改變f功能的API。

1

the documentation

CPython的實現細節:CPython的目前使用引用計數的方式與(可選)延遲循環鏈接的垃圾,其一旦收集最對象,因爲他們成爲不可達的檢測,但不保證收集包含循環參考的垃圾。有關控制循環垃圾收集的信息,請參閱gc模塊的文檔。其他實現的行爲不同,CPython可能會改變。 不依賴於對象的直接定稿時,他們變得不可(例如:始終關閉文件)。

短期改變自己的解釋,你無法實現你想要的。當口譯員決定執行時,將會調用__del__

+0

或者你自己來電話。即使如此,如果有的話,內存可能不會立即回收。 – martineau

+0

謝謝你的報價。它證明在CPython中沒有記錄和未來證明的方法。我澄清了這個問題:我甚至會接受一個在CPython 2.7中工作的未公開的解決方案。 – pts

+0

@martineau:手動調用'm .__ del __()'不會幫助我。我不需要調用__del__,我只是使用'__del__'作爲Python解釋器想要刪除對象的指示符。我關心早期被刪除的對象。 – pts