次の例について考えてみます。
with open('a.txt') as f:
pass
# Is f supposed to be defined here?
私はwith-statementとPEP-343の言語ドキュメント(2.7)を読みましたが、私が知る限り、彼らはこの問題について何も述べていません。
CPython 2.6.5 fではwithブロックの外で定義されているようですが、変更される可能性のある実装の詳細には依存しません。
次の例について考えてみます。
with open('a.txt') as f:
pass
# Is f supposed to be defined here?
私はwith-statementとPEP-343の言語ドキュメント(2.7)を読みましたが、私が知る限り、彼らはこの問題について何も述べていません。
CPython 2.6.5 fではwithブロックの外で定義されているようですが、変更される可能性のある実装の詳細には依存しません。
回答:
はい、コンテキストマネージャはwithステートメントの外で使用でき、実装やバージョンに依存しません。withステートメントは、新しい実行スコープを作成しません。
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()
コンテキストマネージャは、複数回使用される場合があります。
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 の「仕様:「with」ステートメント」セクションをご覧ください。Pythonのスコープルール(苛立たしいかもしれません)fも同様に適用されます。
[x for x in [1]]。xそれ以外でも利用できます。それをジェネレーターにします(x for x in [1])。現在xご利用いただけません。これはPython 3で変更されたので、リスト内包表記でもxリークしないように思い出したようですが、現在、参照を見つけることができません。
コメントでのHeikkiの質問に答えるために:はい、このスコープ動作はPython言語仕様の一部であり、準拠しているすべてのPython(PyPy、Jython、IronPythonを含む)で動作します。