<Python> でこでこでこでこでこれーた。

デコレータ decorator
難しい。

元の関数 function になんらかの変更をして、元の関数と置き換えるものっぽい。

ちこっと試してみた。

まずはデコレータ定義。

In [144]: def deco(func):
     ...:     def wrapper():
     ...:         return func() + 100
     ...:     return wrapper
     ...: 

で、もとの関数定義。

In [145]: def aaa():
     ...:     return 10
     ...: 

In [146]: aaa()
Out[146]: 10

で、デコる。

In [147]: @deco
     ...: def aaa():
     ...:     return 10
     ...: 

関数aaaは、、

In [148]: aaa()
Out[148]: 110

置き換わる。
ふーん、、、

もうちょい試す。
aaaを元に戻す。

In [149]: def aaa():
     ...:     return 10
     ...: 

ものの本によると、デコレータは、下記と同じものらしい。

In [150]: deco(aaa)
Out[150]: <function __main__.deco.<locals>.wrapper>

ふーん、 で、関数を実行する( = ()をくっつける)と、、、

In [151]: deco(aaa)()
Out[151]: 110

なるへそ。
ただ、デコの引数はあくまで関数
関数にしないとゲロる。

In [153]: deco(aaa())()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-153-5fa56bc7f17d> in <module>()
----> 1 deco(aaa())()

<ipython-input-144-c2d756b3bd08> in wrapper()
      1 def deco(func):
      2     def wrapper():
----> 3         return func() + 100
      4     return wrapper
      5 

TypeError: 'int' object is not callable

お前の入れたものaaa()は関数でなくて、intだ! と、、、
なるほど、、

次。
デコ関数中のwrapper()を取っ払うとどうなるか。

In [154]: def deco(func):
     ...:     return func() + 100
     ...: 

関数を渡してみる。

In [155]: deco(aaa)
Out[155]: 110

OK。んじゃ、呼び出し。

In [156]: deco(aaa)()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-156-eb0939644b83> in <module>()
----> 1 deco(aaa)()

TypeError: 'int' object is not callable

ゲロる。
int 110は関数じゃねーだろ、、と。

念のため、デコの書式でもやってみる。

In [157]: @deco
     ...: def aaa():
     ...:     return 10
     ...: 

In [158]: aaa()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-158-82436be7f896> in <module>()
----> 1 aaa()

TypeError: 'int' object is not callable

ゲロる。一緒。

次。
元関数が引数を取る場合は、wrapper()*argsを追加する。

In [160]: def deco_a(func):
     ...:     def wrapper(*args):
     ...:         return func(*args) + 100
     ...:     return wrapper
     ...: 

In [161]: @deco_a
     ...: def aaa(x):
     ...:     return x
     ...: 

In [162]: aaa(50)
Out[162]: 150

一応、この書式でも試す。

In [163]: def bbb(x):
     ...:     return x
     ...: 

In [166]: deco_a(bbb)(50)
Out[166]: 150

なるほど、、、
ちと理解が深まった気がする。

スタックさん他、参考先

stackoverflow.com

qiita.com

qiita.com

www17.atpages.jp