はじめに
今回は初学者がつまずきやすいとされている、Pythonのデコレータについてまとめます。
デコレータとは
デコレータとは、あるオブジェクトに対し、その構造を変更せずに新しい機能を追加するようなデザインパターン
と言えるでしょう。
自分でも何を言っているのか、よくわからないので具体例をみていきましょう。
先にソースコード全体を貼り付けておきます。
ソースコード
1 | def my_decorator(my_func): |
関数を修飾する
いま、以下のような関数func
が存在するとしましょう。
1 | def my_func(): |
あなたは、この関数が呼び出される前に、処理0
を追加したいとします。
その場合、以下のようにするのが良いでしょう。
1 | if __name__=='__main__': |
では、関数my_func
がプログラムの中で複数回呼び出され、かつその全ての呼び出し前に処理0
を追加したい場合はどうしますか。
全ての関数my_func
の前に処理0
を追加するのは面倒ですし、追加漏れが発生してバグの温床にもなりそうです。
であれば、関数my_func
自体に処理0
を追加してしまえば良いでしょう。
1 | def my_func(): |
これで問題ありません。
しかし、関数my_func
があなたがプログラムで定義している関数ではなく、ライブラリで定義されている関数の場合はどうでしょうか。
その場合は、関数を編集することはできません。
そういった時は、関数を引数として受け取り、関数を返却する関数
を考えれば良いのです。
そんな事ができるのかと思れるかもしれませんが、実際にコードをみてみましょう。
1 | def my_decorator(my_func): |
関数my_decorator
は関数my_func
を引数にとり、関数decorator_func
を返却します。
関数my_decorator
を見ればわかるように、処理0
の後に関数my_func
を呼び出しています。
これを応用すると、関数my_func
の後に処理を行うこともできます。
1 | def my_decorator(my_func): |
さて、関数my_decorator
を作る事ができたので、関数my_func
を更新してみましょう。
1 | def my_decorator(my_func): |
実行結果は、
1 | 処理0 |
となり上手くいったようです。
シンタックスシュガー
さて、実は以下のコードですが、
1 | def my_func(): |
以下のコードでも等価となります。
1 |
|
若干、記述が簡潔になりました。
これがデコレータとして出てくる@
の正体でした。
なお、プログラミングの世界では、ある構文をより簡単に記述できるようにした構文をシンタックスシュガー
と呼んだりします。
まとめ
これで、コードが完成しました。
1 | def my_decorator(my_func): |
最初に述べたとおり、デコレータとは、あるオブジェクトに対し、その構造を変更せずに新しい機能を追加するようなデザインパターン
です。
そのため厳密には、関数に関数を修飾させる処理
だけがデコレータではないので、その点には注意してください。
記事情報
- 投稿日:2020年3月13日
- 最終更新日:2020年3月13日