Home

With文の基本動作

 

拙著「Pythonでデータ分析」においてwith文を用いているが、その動作を簡単に確認してみる。

With文の形式は、以下のようである。

 

with オブジェクト生成式 as target: スィート

 

オブジェクト生成式において用いられるクラス型は、2つのメソッド__enter__(self)__exit__(self, p0, p1, p2)が宣言されていなければならない。

メソッド__enter__(self)は、with文のスィート(すなわちブロック)の実行前に呼び出される。その戻り値はtargetに設定される。

メソッド__exit__(self, p0, p1, p2)は、with文のスィートの実行後に呼び出される。パラメータp0, p1, p2は、スィート内で例外が生成されたときの情報が設定され、それらの値は__exit__内で例外処理を行うときに用いられる。まず、例外処理を行わない例を示し、その後、例外処理を行う例を示す。

With文用の簡単なクラス型を以下のように用意してみた。

 

class MyClass:

    def __init__(self, mymsg):

        self.mymsg = mymsg

    def __enter__(self):

        print('開始します。')

        return self.mymsg

    def __exit__(self, p0, p1, p2):

        print('終了します。')

 

関数__enter__の実行時に、「開始します。」が出力され、クラス型のオブジェクト生成時のパラメータmymsgが関数__enter__の関数値としてwith文のtargetに設定される。

関数__exit__は、「'終了します。’」の出力のみを行う。

上のクラス型MyClassを用いるwith文を次のように書いてみた。

 

with MyClass('例です。') as msg:

    print('処理中です。')

print(msg)

 

このコードを実行すると以下の出力が得られる。

 

開始します。

処理中です。

終了します。

例です。

 

関数__enter__が実行されたときの出力「開始します。」、with文のスイートのprint('処理中です。')による出力「処理中です。」、関数__exit__による出力「終了します。」、with文終了後ののprint(msg)による出力「例です。」が順番に出力されている。

上のサンプルプログラムを1つのスクリプトにまとめたものを、リスト1に示す。

 

リスト1

 

class MyClass:

    def __init__(self, mymsg):

        self.mymsg = mymsg

    def __enter__(self):

        print('開始します。')

        return self.mymsg

    def __exit__(self, p0, p1, p2):

        print('終了します。')

 

with MyClass('例です。') as msg:

    print('処理中です。')

print(msg)

 

 

例外に対応する例

 

リスト2に例外処理を行うスクリプト例を示す。

 

リスト2 例外の処理

 

class MyClass:

    def __init__(self, mymsg=''):

        self.mymsg = mymsg

    def __enter__(self):

        print('開始します。')

        return self

    def __exit__(self, p0, p1, p2=None):

        if p2 == None:

            print('終了します。')

        else:

            print('例外の発生')

    def ShowMsg(self):

        print(self.mymsg)

 

import sys

 

try:

    with MyClass('例です。') as check:

        a = int(input('a = '))

        b = int(input('b = '))

        c = a / b

        print('a/b =', c)

except:

    print(*sys.exc_info())

 

check.ShowMsg()

print('スクリプト実行終了。')

 

割り算

c = a / b

において、b=0のときは、0による割り算の例外が生起する。このとき、with文のスィート部を抜け出すときにメソッド__exit__が呼び出されるとともに、except部が実行されて例外の処理が行われる。実行例を以下に示す。

 

開始します。

a = 1

b = 0

例外の発生

<class 'ZeroDivisionError'> division by zero <traceback object at 0x00000201BE165900>

例です。

スクリプト実行終了。

 

 

 

Home