デコレータは、既存の関数のソースコードを直接書き換えることなく、「関数の実行前後」に新しい機能を追加・拡張するための強力な仕組みです。
一言でいうと、「関数をラップ(包む)して、中身を付け足すもの」とイメージしてください。
1. デコレータの基本構造
デコレータは、「関数を引数にとり、新しい関数(wrapper)を返す関数」です。
Python
def my_decorator(func):
def wrapper():
print("--- 実行前の処理 ---")
func() # 元の関数を実行
print("--- 実行後の処理 ---")
return wrapper
@my_decorator
def say_hello():
print("こんにちは!")
say_hello()
実行結果:
--- 実行前の処理 ---
こんにちは!
--- 実行後の処理 ---
@my_decorator という記述が「この関数をデコレータで包む」という合図(糖衣構文)です。
say_hello 関数は、実際には my_decorator が返した wrapper に置き換わっています。
2. なぜデコレータを使うのか?
「関数の中身を書き換えればいいのでは?」と思うかもしれませんが、デコレータには以下のメリットがあります。
DRY原則(同じコードを書かない): 複数の関数で「ログ出力」「実行時間の計測」「ログインチェック」などの共通処理が必要な場合、デコレータ一つで対応できます。
既存コードを汚さない: 元の関数の機能を変更せずに、外側から機能を追加できるため、バグを混入させにくいです。
3. 【実践】実行時間を計測するデコレータ
実際の開発でよく使われる、関数の実行時間を計測する例です。
Python
import time
def timer_decorator(func):
def wrapper(*args, **kwargs): # 引数を受け取れるようにする
start = time.time()
result = func(*args, **kwargs) # 元の関数の戻り値を保持
end = time.time()
print(f"実行時間: {end - start:.4f}秒")
return result # 戻り値を返す
return wrapper
@timer_decorator
def heavy_task(n):
time.sleep(n)
return "完了"
print(heavy_task(1))
*args, kwargs を使うことで、どんな引数を持つ関数にも対応できるようになります。
return result を書くことで、元の関数の戻り値をそのまま呼び出し元に渡せます。
4. まとめ:デコレータ習得のステップ
まずは「ラップするだけ」の関数を作る: 上記の wrapper パターンを真似して書いてみる。
引数と戻り値に対応する: *args と return を意識する。
既存の便利なデコレータを使う: Python標準の @staticmethod や @classmethod、あるいはWebフレームワーク(Flaskなど)でよく使われる @app.route() などに触れてみる。
デコレータを使えるようになると、「関数を部品として扱う」感覚が身につき、コードが劇的に洗練されますよ。
0 件のコメント:
コメントを投稿