Python の二種類のデコレータ ― 2022年05月26日 11時29分57秒
引数無しのデコレータと functools.wraps の解説があり、引数ありのデコレータの解説がある。
簡単にまとめると、デコレータとは関数を引数に実行される関数の呼び出し。実例を見た方が断然分かりやすい。コードは上記のところから引用。
デコレータのこの表記は、
@logged
def f(x):
"""does some math"""
return x + x * x
以下の表記と同じ。
def f(x):
"""does some math"""
return x + x * x
f = logged(f)
関数の実装を置き換えている。
この置き換え時に、Python の内部変数名も替えておくと色々と便利。そこで functools.wraps が使える。
from functools import wraps
def logged(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
@logged
def f(x):
"""does some math"""
return x + x * x
print(f.__name__) # prints 'f'
print(f.__doc__) # prints 'does some math'
それ自体が引数を取るデコレータだとかなりややこしくなって、関数を返す関数を二重で行う必要がある。理屈としては、
@decorator_with_args(arg)
def foo(*args, **kwargs):
pass
が
foo = decorator_with_args(arg)(foo)
に成るから、一段深くなる。
最終的に、以下の定型文になる。
def decorator_factory(argument):
def decorator(function):
def wrapper(*args, **kwargs):
funny_stuff()
something_with_argument(argument)
result = function(*args, **kwargs)
more_funny_stuff()
return result
return wrapper
return decorator
何度見ても折り込み等で混乱する。
最近のコメント