PythonのWebフレームワーク使うなら知っておきたいデコレータ
最近「オワタ\(^o^)/」で有名なDjangoしか触ってないダメ人間です。
こんにちは。
Djangoとかどうでもいいがな、
Webフレームワークとかめんどくさいがな、
という最近なのでDつながりでDecoratorの話をします。
ナウでヤングなPythonistaのホットな話題はGCの参照カウンタ、
ではなくてFlaskとかかもしれないですが、
@app.route("/") def hello(): return "Hello World!"
こいつも多分に漏れずDecoratorを使います。
Djangoでも、
@require_GET
とか
@require_POST
とか使ったり見たことがあるんじゃないかと思います。
で、意外と魔法っぽいデコレータですが、
これっていったいどうなってんの?
って事を知らない人が割といたりします。
「とりあえず指定しろって言われたから指定してますサーセンwww」
という感じ何じゃないでしょうか。
なので、よく使われがち&便利でかつ
「デコレータにした方が良いケースなのにロジック記述になってる」なんてことも多々ありますので、
ヤングなPythonistaに「んなこと知ってんだよ」と言われながらも
デコレータについて書いてみようと思います。
Pythonのデコレータってそもそもシンタックスシュガーなんですが、
簡単に言うと、
・デコレータで指定した関数を受け取り、その関数そのものないしはその関数を呼び出す関数を返す
という用途で使われます。
【関数そのものを返す】場合はデコレータ引数とその関数を何らかに関連づけたい、とかで使いますし、
【関数を呼び出す関数を返す】場合はフック関数として使われることが殆どかと思います。
で、Webフレームワークだとこんな感じ。
オールドタイプなのでDjangoスタイルで。
# -*- coding: utf-8 -*- # デコレータ def require_foo(foo_type): def decorator(func): # func はこの場合 bar (関数オブジェクト) # bar の前にフックする関数をラップしてそれを返すことができる def inner(request, *args, **kwargs): # このデコレータに修飾された関数はこのinnerにラップされる request += foo_type # 適当だが return func(request, *args, **kwargs) return inner return decorator @require_foo('hoge') def bar(request): # Django のviewと思ってね return request if __name__ == '__main__': request = 'Hallo World.' print bar(request) # bar は innerである print bar print bar.func_name
デコレータが引数を必要とするので
def require_foo(foo_type):
が一番外にありますが、引数がいらない場合はこれはいらないです。
http://codepad.org/cRsvoqrt
ここで問題として、
print bar
とすると
とかになります。
print bar.func_name
も
inner
です。(ラップ関数の方をbarに代入しているので当たり前ですが)
これだと困るという場合には、
from functools import wraps
を使ってください。
http://codepad.org/HVjuRZMS
@wraps(func)
をinnerにつけるだけで関数名を正してくれます。
普段適当にデコレータを使うと可読性も下がりますが、
Webフレームワークの場合にはデコレータ自作することも多々ありますし、
@require_POST @require_GET def hoge(request): pass
みたいに重ねることもあるでしょうから、
何が起きているのか憶えておくとお得です!(デコレータチェインの動作とか、一応ね)
Webフレームワークの話じゃねえええ、という文句は次の人に言ってください。
次はとらドラ好きで有名な渋川さんがいいのかなあとか。
(スルーされたので@takanoryで? 未確定)
参考文献。
- 作者: Tarek Ziade,稲田直哉,渋川よしき,清水川貴之,森本哲也
- 出版社/メーカー: アスキー・メディアワークス
- 発売日: 2010/05/28
- メディア: 大型本
- 購入: 29人 クリック: 691回
- この商品を含むブログ (83件) を見る