2011-02-16 49 views
7

我想知道爲什麼使用with()語句或在塊中打開的文件對象在退出後仍保留在範圍內。 '<'關閉了文件'>'的對象嗎?爲什麼上下文在with語句後四處停留?

>>> with open('test.txt','w') as f: 
...  f.write('test') 
... 
>>> f 
<closed file 'test.txt', mode 'w' at 0x00E014F0> 
>>> f.close() 


>>> if True: 
...  fal = open('demo.txt','w') 
...  fal.write('stuff') 
...  fal.close() 
... 
>>> fal 
<closed file 'demo.txt', mode 'w' at 0x00E015A0> 
+2

這裏是[PEP 343](http://www.python.org/dev/peps/pep-0343/)的一些輕讀。 – 2011-02-16 20:13:06

回答

14

在Python新型示波器(又名命名空間)是的模塊,類和函數創建的,而不是任何其他聲明,尤其不適合withif塊。綁定在withfor語句體內的標識符因此被綁定在最內層的範圍內,這是您的案例中交互式解釋器的頂層範圍。只要這個範圍是有效的,或者直到它們明確地從範圍中刪除(通過使用del fal中的del),標識符就被綁定在範圍內。

只有當對象不再被引用時才能清理對象。然而,實際上這個對象真正被清理的時刻是未定義的。 Python使用垃圾收集進行內存管理,並且不執行特定的策略。在使用引用計數的CPython中,一旦最後一個引用超出範圍,對象立即被清除。像PyPy或Jython這樣的替代實現使用更高級的垃圾回收器,它可以在任意時間點清理未引用的對象。

這意味着,勢必ffal在您的示例對象bascially從不清理,因爲交互式解釋的頂層範圍不自然存在,只要interpeter運行。但是請注意,這實際上並不是一個問題,因爲它們仍然是正確關閉的,並且不再聲明任何文件資源,而只是一些內存。

0

文件對象,就像任何其他的對象,「徘徊」爲你的程序的時間,直到它刪除(它__del__方法被調用)。

del f將導致f被Python的垃圾收集器垃圾收集。當你退出一個作用域時,腳本終止,或者在你的例子中,解釋器會話結束,這會自動發生。

+2

這是誤導。當沒有更多的引用時,Python將刪除該對象,`del f`將只刪除一個對`f`引用的對象的引用。 – delnan 2011-02-16 20:14:26

+0

沒錯,但我指的是`del f`作爲他的例子的一部分,它只有一個引用(他可以讀入python GC的引用計數機制的複雜性以作更深入的解釋)。 – Aphex 2011-02-16 20:17:29

+0

如果是這種情況,那麼'__exit__包裝器是with()語句的一部分,調用__del__,我不明白如何在with語句內對變量進行範圍映射,並不會導致它完全清理。在我的例子中,沒有更多的引用'f'。它被聲明在'with()'語句中 – pyInTheSky 2011-02-16 20:19:04

4

該名稱將保留在範圍內,直到您離開範圍。

如果你想清理的對象,分配不同的價值的名稱,如

f = None 

這不會關閉該文件!

通過將程序構建到函數(可能是類)中來限制作用域是個好習慣。這使得它更具可讀性,並使未綁定的對象(範圍內沒有引用該對象的名稱)成爲垃圾收集的可選項。

這通常不是一個問題,當你使用的提示雖然:)

0

Python的with語句調用文件類的__exit__方法[其中,在文件的情況下,關閉它們。它不會刪除該對象;只有在您明確清理或關閉程序/解釋程序時纔會清理它。