python - 関数デコレータ
デコレート対象関数の実行前後に処理を追加する。
使用方法は、対象関数の定義の上の@デコレータ名を追加する。
@deco def myfunc(x):
とすることで、myfuncをdecoの引数にするイメージ?
def deko(myfunc) def wrapper(x): do_something return wrapper
使用例
myfuncは引数に負数を渡されるとValuErrorになる。
デコレータdeco_test1はmyfunc実行前に引数を確認して負数の場合はゼロに置き換える。
# coding: cp932 def deco_test1(f): # f はデコレート対象の関数 """" 関数デコレータ デコレート対象の関数の引数が負数の場合は ゼロを引数として関数に渡す """ def wrapper(x): # x はfの引数 if x < 0: v = 0 else: v = x r = f(v) return r return wrapper @deco_test1 def myfunc(x): """ xが負数の場合はエラー その他の場合は、x*x """ if x < 0: raise ValueError("値が負数です") return x * x print(myfunc(2)) # -> 4 print(myfunc(-1)) # -> 0 デコレートしていない場合はValueError
デコレータが引数を持つ場合
デコレータが引数を持つようになったので、wrapper関数の外側に、デコレート対象関数を引数とするdecorate関数を追加する。
デコレータdeco_test2は引数maxを持ち、myfunc実行結果がmaxより大きい場合はmaxに置き換える。
# coding: cp932 def deco_test2(max): # max はデコレータの引数 """" 関数デコレータ デコレート対象の関数の引数が負数の場合は ゼロを引数として関数に渡す 関数の戻り値が関数デコレータの引数より大きい場合は引数に置き換える """ def decorator(f): # f はデコレート対象の関数 def wrapper(x): # x はfの引数 if x < 0: v = 0 else: v = x r = f(v) if r > max: r = max return r return wrapper return decorator @deco_test2(50) # 戻り値のmaxを50とする def myfunc(x): """ xが負数の場合はエラー その他の場合は、x*x """ if x < 0: raise ValueError("値が負数です") return x * x print(myfunc(2)) # -> 4 print(myfunc(-1)) # -> 0 デコレートしていない場合はValueError print(myfunc(7)) # -> 49 print(myfunc(8)) # -> 50 デコレートしていない場合は64