pythonのwith文法の深い理解

2838 ワード

ファイル、ネットワーク接続、ロックなどのオブジェクトがある場合は、with文をサポートする必要があります.次に、2つの定義方法について説明します.
方法(1):
まずwith動作原理(1)withの直後の文が評価されると、オブジェクトを返す「_enter_()」メソッドが呼び出され、このメソッドの戻り値はasの後の変数に与えられる.(2)with後のコードブロックが全て実行されると、前に返されるオブジェクトの"_exit_()"メソッドが呼び出される.
with動作原理コード例:
class Sample:
    def __enter__(self):
        print "in __enter__"
        return "Foo"
    def __exit__(self, exc_type, exc_val, exc_tb):
        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()メソッドが呼び出される.
【注:】exit()メソッドには3つのパラメータがあり、exc_type, exc_val, exc_tb,これらのパラメータは異常処理においてかなり有用である.exc_type:エラーのタイプexc_val:エラータイプに対応する値exc_tb:コード内でエラーが発生した位置例コード:
class Sample():
    def __enter__(self):
        print('in enter')
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print "type: ", exc_type
        print "val: ", exc_val
        print "tb: ", exc_tb
    def do_something(self):
        bar = 1 / 0
        return bar + 10
with Sample() as sample:
    sample.do_something()

プログラム出力結果:
in enter
Traceback (most recent call last):
type:  
val:  integer division or modulo by zero
  File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 36, in 
tb:  
    sample.do_something()
  File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 32, in do_something
    bar = 1 / 0
ZeroDivisionError: integer division or modulo by zero

Process finished with exit code 1

  
方法(2):
新しいコンテキストマネージャを実現する最も簡単な方法はcontexlibモジュールの@contextmanager装飾器を使用することです.コードブロックタイミング機能を実装したコンテキストマネージャの例を次に示します.
import time
from contextlib import contextmanager

@contextmanager
def timethis(label):
    start = time.time()
    try:
        yield
    finally:
        end = time.time()
        print('{}: {}'.format(label, end - start))

  
# Example use
with timethis('counting'):
    n = 10000000
    while n > 0:
        n -= 1

  
関数timethis()では、yieldの前のコードがコンテキストマネージャで_として使用されます.enter__()メソッドが実行され、yield以降のすべてのコードが__として使用されます.exit__()メソッドが実行されます.異常が発生した場合、異常はyield文に投げ出されます.
【注】1、@contextmanagerは、含まれているコンテキスト管理関数のみを書くために使用する必要があります.2、ファイル、ネットワーク接続、ロックなどのオブジェクトがあり、with文をサポートする必要がある場合は、単独で実装する必要があります.enter__()メソッドと__exit__()メソッド.
転載先:https://www.cnblogs.com/feifeifeisir/p/11475732.html