Python学習8:コンテキストマネージャ(context manager)

4285 ワード

コンテキストマネージャ(context manager)はPython 2である.5オブジェクトの使用範囲を指定するためにサポートされる構文を開始します.使用範囲に入るか離れると、オブジェクトにメモリを割り当てたり解放したりするなど、特別な操作が呼び出されます.文法の形式はwith...as...
 
ファイルを閉じる
ファイルを開き、読み書きし、ファイルを閉じる操作を行います.プログラマーはよくファイルを閉じるのを忘れます.コンテキストマネージャは、ファイルを必要としないときに自動的にファイルを閉じることができます.
次の2つのプログラムを見てみましょう.
# without context manager
f = open("new.txt", "w")
print(f.closed)               # whether the file is open
f.write("Hello World!")
f.close()
print(f.closed)

および:
# with context manager
with open("new.txt", "w") as f:
    print(f.closed)
    f.write("Hello World!")
print(f.closed)

2つのプログラムは実際に同じ操作を実行します.私たちの第2セグメントのプログラムはコンテキストマネージャ(with...as...)を使用しています.コンテキストマネージャには、それに属するブロックがあります.所属するブロックの実行が終了すると(つまりインデントしない)、コンテキストマネージャは自動的にファイルを閉じます(f.closedでファイルが閉じているかどうかをクエリーします).インデントを用いてファイルオブジェクトfの使用範囲を規定することに相当する.
 
上のコンテキストマネージャはfオブジェクトの__に基づいています.exit__()特殊な方法(特殊な方法を利用して様々な文法を実現する方法を覚えていますか?特殊な方法と多様性を参照してください).コンテキストマネージャの構文を使用する場合、Pythonは実際にブロックに入る前にオブジェクトの__を呼び出すように要求されます.enter__()メソッド、ブロック終了時に呼び出す_exit__()メソッド.ファイルオブジェクトfについては、__が定義されているenter__()と_exit__()メソッド(dir(f)で見ることができる).fの__でexit__()メソッドにはselfがある.close()文.コンテキストマネージャを使用する場合は、fファイルを明示的に閉じる必要はありません.
 
ツールバーの
任意の定義enter__()と_exit__()メソッドのオブジェクトは、コンテキストマネージャで使用できます.ファイルオブジェクトfは内蔵オブジェクトであるため、fは自動的にこの2つの特殊な方法を有し、カスタマイズする必要はない.
withの直後の文が評価された後、オブジェクトの__を返します.enter__()メソッドが呼び出され、このメソッドの戻り値はasの後ろの変数に割り当てられます.withの後のコードブロックがすべて実行されると、前に返されるオブジェクトの__が呼び出されます.exit__()メソッド.
次に、コンテキストマネージャ用のオブジェクトをカスタマイズします.
class Sample:
    def __enter__(self):
        print "In __enter__()"
        return "Foo"
 
    def __exit__(self, type, value, trace):
        print "In __exit__()"
 
 
def get_sample():
    return Sample()
 
 
with get_sample() as sample:
    print "sample:", sample

実行結果は次のとおりです.
In __enter__()
sample: Foo
In __exit__()

1. __enter__()メソッドが実行されます
2. __enter__()メソッドが返す値-この例では「Foo」であり、変数'sample'に付与されます.
3.コードブロックを実行し、印刷変数「sample」の値が「Foo」
4. __exit__()メソッドが呼び出されます
withの本当の強みは、異常を処理できることです.Sampleクラスの__に気づいたかもしれませんexit__方法には3つのパラメータ-val,type,traceがある.これらのパラメータは異常処理においてかなり有用である.exc_type, exc_value,tracebackは異常を記述するために用いられ,この3つのパラメータに基づいて対応する処理を行うことができる.正常な動作が終了した場合、この3つのパラメータはNoneです.コードを変更して、具体的にどのように動作しているかを見てみましょう.
class Sample:
    def __enter__(self):
        return self
 
    def __exit__(self, type, value, trace):
        print "type:", type
        print "value:", value
        print "trace:", trace
 
    def do_something(self):
        bar = 1/0
        return bar + 10
 
with Sample() as sample:
    sample.do_something()

この例ではwithの後のget_Sample()はSample()になりました.これは何の関係もありません.withの後の文に続くオブジェクトが__であれば.enter__()と_exit__()メソッドでいいです.この例ではSample()の_enter__()メソッドは、新しく作成したSampleオブジェクトを返し、変数sampleに値を割り当てます.
コード実行後:
type: 
value: integer division or modulo by zero
trace: 
Traceback (most recent call last):
  File "./with_example02.py", line 19, in 
    sample.do_something()
  File "./with_example02.py", line 15, in do_something
    bar = 1/0
ZeroDivisionError: integer division or modulo by zero

実際、withの後ろのコードブロックに異常が投げ出された場合、_exit__()メソッドが実行されます.例に示すように、異常放出時に関連付けられたtype,value,stack traceが__に渡されるexit__()メソッドなので、投げ出したZeroDivisionError異常がプリントアウトされました.ライブラリを開発するとき、リソースを整理したり、ファイルを閉じたりする操作は、__に置くことができます.exit__方法の中で.
したがって、Pythonのwith文は、コードをより簡潔にし、異常が発生した場合、クリーンアップ作業をより簡単にする有効なメカニズムを提供します.
 
まとめ:
コンテキストマネージャを使用して、プログラムの異なる区間でオブジェクトの特性を制御します.コンテキストマネージャ(with EXPR as VAR)は、次のようなプロセスにほぼ相当します.
# with EXPR as VAR:

VAR = EXPR
VAR = VAR.__enter__()
try:
    BLOCK
finally:
    VAR.__exit__()

コンテキストマネージャの利便性のため、使用する価値のあるツールです.
おすすめブログ:http://python.42qu.com/11155501