<Python> でこでこでこでこでこれーた。
デコレータ decorator
。
元の関数 function
になんらかの変更、デコレートdecorate
をして、元の関数と置き換えるものっぽい。
ちこっと試してみた。
まずは、ベースの関数作成&動作確認。
In [32]: def aaa(*args, **kwargs): ...: '''return args/kwargs''' ...: return '{} {}'.format(args, kwargs) ...: ...: In [33]: aaa.__name__ Out[33]: 'aaa' In [34]: aaa.__doc__ Out[34]: 'return args/kwargs' In [35]: aaa(1, 2, key=1) Out[35]: "(1, 2) {'key': 1}"
で、デコレーター関数作成。
関数func
を引数にとって、
で、ラッパー関数wrapper
を定義して、そのラッパー関数を返すreturn
する。
元の関数func
の引数*args, **kwargs
は、ラッパー関数wrapper
に渡す。
In [36]: def deco(func): ...: '''add tag''' ...: def _wrapper(*args, **kwargs): ...: return '<tag>' + func(*args, **kwargs) + '<tag>' ...: return _wrapper ...: ...: In [37]: deco.__name__ Out[37]: 'deco' In [38]: deco.__doc__ Out[38]: 'add tag'
で、デコる、動作確認。
In [39]: @deco ...: def aaa(*args, **kwargs): ...: '''return args/kwargs''' ...: return '{} {}'.format(args, kwargs) ...: ...: In [40]: aaa(1, 2, key=1) Out[40]: "<tag>(1, 2) {'key': 1}<tag>" In [41]: aaa.__name__ Out[41]: '_wrapper' In [42]: aaa.__doc__
ここで、ミソは、デコレーターは、元の関数名を置き換えちゃうらしい。
なので、それを解決するには、functools.wraps
を使うとのこと。
In [43]: import functools In [44]: def deco(func): ...: '''add tag''' ...: @functools.wraps(func) ...: def _wrapper(*args, **kwargs): ...: return '<tag>' + func(*args, **kwargs) + '<tag>' ...: return _wrapper ...: ...: In [45]: @deco ...: def aaa(*args, **kwargs): ...: '''return args/kwargs''' ...: return '{} {}'.format(args, kwargs) ...: ...: In [46]: aaa(1, 2, key=1) Out[46]: "<tag>(1, 2) {'key': 1}<tag>" In [47]: aaa.__name__ Out[47]: 'aaa' In [48]: aaa.__doc__ Out[48]: 'return args/kwargs'
ふーん。なるほど。
あとは、さらに、デコ関数が引数を取る場合。
デコ関数のネストを一段深くする必要あるらしい。。。
In [55]: def deco(tag): ...: def _deco(func): ...: '''add tag''' ...: def wrapper(*args, **kwargs): ...: return '<' + tag +'>' + func(*args, **kwargs) + '<' + tag + '>' ...: return wrapper ...: return _deco ...: ...: In [56]: deco Out[56]: <function __main__.deco(tag)> In [57]: @deco('bold') ...: def aaa(*args, **kwargs): ...: '''return args/kwargs''' ...: return '{} {}'.format(args, kwargs) ...: ...: In [58]: aaa(1, 2, key=1) Out[58]: "<bold>(1, 2) {'key': 1}<bold>"
参考先