ラッパー
ラッパーには大まかに、以下の3つがある。
- 引数を細工して元の関数を呼び出す
- 元の関数を呼び出した後、結果に細工をする
- 前後に処理を追加する
import inspect
"""
Python ラッパーとデコレータ
"""
# 元の関数
def infected(COVID_19_flg):
if COVID_19_flg:
return 'infected'
else:
return 'uninfected'
# 1.引数を細工して元の関数を呼び出す
def wear_mask(func):
def wrapper(COVID_19_flg):
if COVID_19_flg:
COVID_19_flg = False
return func(COVID_19_flg)
return wrapper
# 2.元の関数を呼び出した後、結果に細工をする
def passed_2weeks(func):
def wrapper(COVID_19_flg):
ret = func(COVID_19_flg)
if ret == 'infected':
ret = 'uninfected'
return ret
return wrapper
# 3.前後に処理を追加する
def output_log(func):
def wrapper(*args, **kargs):
print(f'### START {inspect.currentframe().f_code.co_name} ###')
ret = func(*args, **kargs)
print(f'### END {inspect.currentframe().f_code.co_name} ###')
return ret
return wrapper
COVID_19_flg = True
func_1 = wear_mask(infected)
print(func_1(COVID_19_flg)) # マスクしているのでuninfected
func_2 = passed_2weeks(infected)
print(func_2(COVID_19_flg)) # 2週間経ったのでuninfected
func_3 = output_log(infected)
print(func_3(COVID_19_flg)) # STARTとENDのログが出力
デコレータ
デコレータはラッパーのコードの最後の部分に記載していた以下のような記述を簡単に行える。
## ~~~~~~~~~~~~~~省略~~~~~~~~~~~~~
func_3 = output_log(infected)
## デコレータを使うと以下のようになる
@output_log
def infected(COVID_19_flg):
if COVID_19_flg:
return 'infected'
else:
return 'uninfected'
簡単に「hello!」とログを出力するだけのプログラムをデコレータをつかって考えてみると以下のようになる。
def output_log(func):
def wrapper(*args, **kargs):
print(f'### START {inspect.currentframe().f_code.co_name} ###')
ret = func(*args, **kargs)
print(f'### END {inspect.currentframe().f_code.co_name} ###')
return ret
return wrapper
# デコレータ付き関数
@output_log
def print_hello():
print('hello!')
今回は説明しないが、関数以外の引数を受け取るデコレータを作る場合、今回説明したものに加え、もう1階層上に「関数以外の引数を受け取る専用の高階関数」を作る必要が出てくる。