キタコレ
デコレータがわからず悶々としていたが、またまたmorchin氏のコメントに助けられた。
2008-03-08 - rindai87の日記
特に難しい処理はしていません。deco(foo2)で、deco関数をfoo2を引数として呼び出しています。
関数decoは、print ”Hello, world!”を実行して、Noneを返します。
foo2 = deco(foo2)つまり、foo2 = Noneとなります。fooも同様です。
??
何のこっちゃと思っていたら、やっぱりそんなに難しいことではなかった。
サンプルコードがよろしくなかったのだろう。
def deco(func): print "I'm deco()" map(func, [1,2,3]) @deco def foo(x): print x def decolation(ls): print "I'm decolation()" def _show(x): print x return map(_show, ls) def main(): @deco def foo2(x): print x print "I'm here!" decolation([1,2,3]) print foo print foo2 foo(1) foo(2) if __name__ == "__main__": main()
結果
D:\workspace\Python\3-10>python test.py I'm deco() 1 2 3 I'm deco() 1 2 3 I'm here! I'm decolation() 1 2 3 None None Traceback (most recent call last): File "test.py", line 31, in <module> main() File "test.py", line 27, in main foo(1) TypeError: 'NoneType' object is not callable
なるほど!
関数のネストみたいになってるね。
そして
@decoと書いてfoo関数の定義が終了した時点でdeco関数が呼び出されていることに注意する必要があります。
逆に言えば、関数定義をしただけで関数が自動実行されるような仕組みがあるとも言えます。
確かに、
@deco def foo(x): print x
とした時点でdeco()が呼び出されている。
さらに、やってることは
foo=deco(foo)
なので、fooはdeco()の返り値を受け取っている。
だから、デコレートした瞬間から、foo()は関数ではない、と。
これはかなり面白いよね!!
クロージャとかを組み合わせると、かなり不思議な挙動を示しそうだ。