18

私はこの質問を見て、あなたがいつ を使いたいのか理解していますが、あなたがいつ使いたいwith foo() as bar:のかわかりません:

bar = foo()
with bar:
   ....

を使用することによる分解の利点が取り除かれているだけではありませんかwith ... as、それとも何が起こっているのか誤解していますか? なぜ誰かがただ使いたいのwithですか?

4

3 に答える 3

12

@freakishの答えを少し拡張するにwithは、「コンテキスト」への入り口と出口を保証します。コンテキストとは一体何ですか?まあ、それは「あなたが持っているものは何でも」です。いくつかの明白なものは次のとおりです。

  • ロック: ロックを取得し、データを操作して、ロックを解放します。
  • 外部ファイル/ストリーム: ファイルを開き、読み書きし、閉じます。
  • データベース レコード: レコードを見つけ (通常はロックも行います)、いくつかのフィールドを使用して変更し、レコードを解放します (ロックも解除します)。

あまり目立たないものには、特定の種類の例外トラップが含まれる場合もあります。ゼロ除算をキャッチし、いくつかの演算を行ってから、キャッチを停止する場合があります。もちろん、これは Python 構文に組み込まれています: try...exceptブロックとして! 実際、これwithは単に Python の try/except/finally メカニズムの特殊なケースです (技術的には、try/finally別のブロックにラップされていtryます。コメントを参照してください)。

ブロックのas一部はwith、コンテキストエントリがブロック内で使用したい値を提供する場合に役立ちます。ファイルまたはデータベース レコードの場合、新しく開かれたストリームまたは取得したばかりのレコードが必要であることは明らかです。例外をキャッチする場合、またはデータ構造のロックを保持する場合、コンテキスト エントリから値を取得する必要がない場合があります。

于 2013-06-11T20:44:00.070 に答える
5

たとえば、使用したい場合Lock()

from threading import Lock
myLock = Lock()
with myLock:
   ...

Lock()オブジェクトは本当に必要ありません。オンになっていることを知っておく必要があります。

于 2013-06-11T20:26:40.700 に答える
4

withなしで使用しasても、まったく同じティアダウンが得られます。コンテキストを表す新しいローカル オブジェクトが得られないだけです。

これが必要な理由は、コンテキスト自体が直接役に立たない場合があるためです。つまり、コンテキストの開始と終了の副作用のためにのみ使用しているということです。

たとえば、Lockオブジェクトの場合、ブロックを有効にするには、そのオブジェクトを既に持っているwith必要があります。したがって、ブロック内でそれが必要になったとしても、それを別の名前に再バインドする理由はありません。コンテキスト マネージャーではないオブジェクトに対してを使用する場合も同様ですcontextlib.closing。オブジェクト自体は既にあるので、何が返されるかは誰が気にしclosingますか?

のようなものsh.sudoでは、使用できるオブジェクトさえありません。

コンテキストマネージャのポイントが、ある状態を隠して自動復元するためだけにある場合もあります。たとえば、-stasher を記述して、ブロック内でtermios.tcsetattr呼び出すことができます。tty.setraw()stash オブジェクトがどのように見えるかは気にしません。気にするのは、それが自動復元されることだけです。

decimal.localcontextこれらの方法のいずれかで動作できます — 既に持っているオブジェクトを渡す (したがって、新しい名前は必要ありません)、名前のない一時オブジェクトを渡す、または現在のコンテキストを隠して auto-復元されました。しかし、それらの場合のいずれかで。

コンテキストが必要な場合もあれば、必要でない場合もあります。たとえば、データベース トランザクションを自動コミットするだけの場合with autocommit(db.begin()):は、ブロック内でアクセスしないため、 と記述できます。ただし、明示的にコミットしない限り自動ロールバックする場合は、おそらく と書くので、ブロック内でwith autorollback(db.begin()) as trans:実行できます。trans.commit()(もちろん、PEP 343transaction例のように、通常の終了時にコミットし、例外時にロールバックするトランザクションが実際に必要になることがよくあります。しかし、ここでより良いハイブリッドの例を思いつきませんでした…)

PEP 343とその前身 (PEP 310、PEP 340、および 343 からリンクされたその他のもの) は、これらすべてをある程度説明していますが、何気なく読んだだけでは理解できないことは理解できます。関連性がなく、主にマイルハイトの概要と実装レベルの詳細を説明するだけで、その間のすべてをスキップしています.

于 2013-06-11T20:43:52.390 に答える