
Python デコレータ 基礎編
目次
概要
本記事では Python デコレーターの基礎について解説します。
デコレーターとは
特定の関数に対して前後の処理を追加できる関数です。
@
見かけるかと思いますが、このことです。
特定の関数をほぼ上書きします。
Python 初心者だと初見でなんじゃと思うかもしれませんが、本記事ではそれについて詳しく解説していきたいと思います。
前知識
改めて Python の関数で何ができるか整理していきましょう。
関数は変数化
Python では関数を一旦適宜したら、変数として扱うことができます。また、その変数自体が関数なので、同様の引数を持ちます。
def increase(a):
return a + 1
def increase_2(a):
return a + 2
def get_increase_function(twice):
if twice:
return increase_2
else:
return increase
some_add = get_increase_function(True)
x = some_add(23) # 25
関数は関数内で定義可能
Python 関数内で関数も定義できます。
def get_increase_function(twice):
def increase(a):
return a + 1
def increase_2(a):
return a + 2
if twice:
return increase_2
else:
return increase
some_add = get_increase_function(True)
x = some_add(23) # 25
デコレータなしの実装
上記で関数の扱い方がわかったことから、次に前処理、後処理を追加するとしましょう。
以下が定番なやり方ではないかと思います。
def increase(a):
return a + 1
def make_sentence_with_idx(idx):
idx = int(idx)
num = increase(idx)
return f"This idx is {num}th(st/nd) element"
前処理が idx の string 化、後処理が fstring に対応します。
1個であれば上記で十分ですが、例えば以下のように同じ前・後処理があった場合、コードが重複がしてしまいます。
def make_sentence_with_idx_2(idx):
idx = int(idx)
num = increase_2(idx)
return f"This idx is {num}th(st/nd) element"
def make_sentence_with_idx_3(idx):
idx = int(idx)
num = increase_3(idx) # not defined
return f"This idx is {num}th(st/nd) element"
前処理、後処理一個でも変更したい場合、全てを書き換える必要が出てきます。 管理・見通し共に悪くなります。 そこで出てくるのが、デコレータです。
デコレータの書き方
定義
デコレータの定義として、基本対象とする関数を第1引数に入れ、それを別の関数でラッピングします。
def decorator(func):
def rewrite_func(idx):
idx = int(idx)
num = func(idx)
return f"This idx is {num}th(st/nd) element"
return rewrite_func
本定義では、func はデコレートしたい関数です。rewrite_func は作り直した関数です。 すると上記で書いた関数は以下のようになります。
# make_sentence_with_idx と等価
@decorator
def increase(a):
return a + 1
@decorator
def increase_2(a):
return a + 2
@decorator
def increase_3(a):
...
ちなみに上記は以下と等価です。
def increase(a):
return a + 1
make_sentence_with_idx = decorator(increase)
# 残り割愛
ユースケース
以下のユースケースでは有効かと思われます。
- 前処理・後処理
- 処理時間の測定
- 値・関数の保持・登録
- 変数の記録
その他
デコレータに対して引数等を用意することもできます。 今回は紹介しませんでしたが、次回以降紹介できれば幸いです。
まとめ
今回デコレータの基本について触れました。また、ユースケース等についても紹介しました。 次回以降は引数の取り方や、functools について記述していこうかと思います。