請看下面的例子:with with語句在with-block之外是否可用定義變量?
with open('a.txt') as f:
pass
# Is f supposed to be defined here?
我已閱讀與語句以及PEP-343,但據我可以告訴他們不要說在這個問題上的任何語言的文檔(2.7) 。
在CPython 2.6.5中f
確實看起來是在with-block之外定義的,但我寧願不依賴於可能改變的實現細節。
請看下面的例子:with with語句在with-block之外是否可用定義變量?
with open('a.txt') as f:
pass
# Is f supposed to be defined here?
我已閱讀與語句以及PEP-343,但據我可以告訴他們不要說在這個問題上的任何語言的文檔(2.7) 。
在CPython 2.6.5中f
確實看起來是在with-block之外定義的,但我寧願不依賴於可能改變的實現細節。
是的,上下文管理器將在with語句之外提供,並且不依賴於實現或版本。用語句不要創建一個新的執行範圍。
在我看來,這是最明確的解釋,因此授予接受的答案;將給Alex和TokenMacGuy指出其他有用的信息。 –
如果f
是一個文件,它將在with
語句之外顯示爲關閉。
例如,這
f = 42
print f
with open('6432134.py') as f:
print f
print f
將打印:
42
<open file '6432134.py', mode 'r' at 0x10050fb70>
<closed file '6432134.py', mode 'r' at 0x10050fb70>
你可以找到部分規格下PEP-0343的細節: '與' 聲明。 Python scope rules(可能是irritating)也適用於f
。
我知道這個,我在問題中提到過。至少CPython 2.6.5。但是,你能保證Jython,IronPython和PyPy同樣適用嗎? –
Python的範圍規則並不總是那麼清晰。在CPython 2.6.5中考慮這一點:'[x for x in [1]]'。外面有'x'。把它變成一個生成器:'(x for [1])''。現在'x'不可用。我似乎記得在Python 3中這已經發生了變化,因此即使使用列表理解'x'也不會泄漏,但我現在找不到參考。 –
我搜索了,但現在還沒有發現任何重要的東西。有趣的問題,雖然。 – miku
的with
語法:
with foo as bar:
baz()
約爲糖:
try:
bar = foo.__enter__()
baz()
finally:
if foo.__exit__(*sys.exc_info()) and sys.exc_info():
raise:
這通常是有用的:例如
import threading
with threading.Lock() as myLock:
frob()
with myLock:
frob_some_more()
上下文管理器可以是使用一種以上一旦。
你確定這將在Jython,IronPython和PyPy中工作嗎? –
好吧,鎖的重用可能會也可能不會(沒有想法,但如果它們不同,它會是一個錯誤) - 但是跨實現的Python範圍規則在這裏肯定是相同的。 – fuzzyman
這再次不是範圍問題。範圍將是相同的。但是,如果foo .__ exit__的實現將線程置於停止狀態,那麼除非鎖具有重新鎖定它的__enter__,否則第二個語句看起來不像對線程鎖有用。 –
回答Heikki的問題:是的,這個範圍界定行爲是python語言規範的一部分,可以在任何和所有兼容的python(包括PyPy,Jython和IronPython)上工作。
f在封閉範圍內是否可用的問題已經得到解答。對於我來說,當我意識到* context *的概念不同於* scope *的概念時,上下文管理器的整個概念就會被點擊。這是一個鏈接到我的網站,希望有一點幫助:http://www.markus-gattol.name/ws/python.html#context_manager – Tom
確切地說 - 上下文是一個改變當前狀態的問題 - 文件打開,文件關閉或線程鎖定/解鎖。設備分配/解除分配。所有在範圍內命名的變量仍然存在 - 但現在它們將指向釋放/關閉/解鎖的句柄。 –