with構文とは
with構文とは後処理が必要な機能を使う際に、使用者がその機能を安全に、そして簡単に使用できるための構文になります。
with構文を使わない場合
with構文を使わないの例をみてみましょう。下のコードになります。
from stove import Stove
stove = Stove()
stuff = 'うどん'
print('%sを作ります。' % stuff)
try:
stove.switch_on()
stove.boil(stuff)
except:
raise
finally:
stove.switch_off()
print('%sができました。' % stuff)
Stoveクラスを使ってうどん茹でています。最初にswitch_onメソッドでコンロに火を点けて、そのあとboilメソッドでうどんを茹でています。そしてfinally句でswitch_offメソッドを呼びコンロの火を消火しています。finally句でswitch_offメソッドを呼び出しているのは、例外が発生しても確実にswitch_offメソッドを呼びたいからです。
finally句は吹きこぼれをしたり、空焚きしてしまうような例外が発生しても確実に消火するための安全装置のようなものになります。
with構文を使用する場合
それでは少し危険なStoveクラスですが、with構文を使用して安全に使用してみましょう。
下のコードになります。
from stove import Stove
stuff = 'うどん'
print('%sを作ります。' % stuff)
with Stove() as stove:
stove.boil(stuff)
print('%sができました。' % stuff)
with構文を使用しない場合に比べてとてもシンプルになりましたが、try,finallyを使用したコードと同じく安全です。まさに安全装置ですね。
with構文で使用できるクラス
それでは、with構文で使用できるクラスとはどのようになっているのかを下の例でみてみます。
class Stove():
def __init__(self):
self.switch = False
def switch_on(self):
if not self.switch:
self.switch = True
print('コンロ点火しました')
def switch_off(self):
if self.switch:
self.switch = False
print('コンロ消火しました')
def boil(self, stuff):
print('%sを茹でました。' % stuff)
def __enter__(self):
self.switch_on()
return self
def __exit__(self, exception_type, exception_value, traceback):
self.switch_off()
今までの例に出てきたswitch_on、switch_off、boilメソッド以外に**__enter__、__exit__**といったメソッドがみることができます。この二つのメソッドがwith構文で使用できるために必要なメソッドになります。
**__enter__**メソッドはwithブロック内で呼び出されます。そして戻り値には自身のインスタンスを返却する必要があります。Stoveクラスではコンロの点火も同時に行っています。
**__exit__**メソッドはwithブロックを抜けたときに呼び出されます。また、例外が発生した場合にもこのメソッドは呼ばれるため、例外処理もここに記述します。通常例外はraiseされますが、このメソッドでTrueを返却すると例外を握りつぶすことができます。
Stoveクラスではコンロの消火を行っています。