はじめに
Python を勉強中の筆者がデコレータを理解するための基本概念や実践的な使用例をまとめてみました。デコレータを理解し、活用することで効率的なコードを書くための一助となれば幸いです。
デコレータの概要
デコレータは、関数やメソッドの振る舞いを変更するための特殊な機能です。既存のコードを変更せずに機能を追加したり、コードの実行前後に特定の処理を行ったりできます。
クロージャの概要
クロージャの理解が必要なため、先にクロージャを軽く説明します。
クロージャは、関数の内部で定義された別の関数です。クロージャは、親関数のスコープ内の変数にアクセスできます。また、この関数の処理結果はクロージャの結果を返します。
def make_multiplier(x):
def multiplier(n):
return x * n
return multiplier
times_two = make_multiplier(2)
print(times_two(3)) # 6
デコレータの基本構造
デコレータは、関数を引数に取り、別の関数を返す関数です。以下は、デコレータの基本的な構造です。
def my_decorator(func):
def wrapper():
# 関数実行前にやりたいこと
result = func()
# 関数実行後にやりたいこと
return result
return wrapper
デコレータは、関数の定義の前に@
記号とともに記述することで適用できます。
@my_decorator
def greet():
return "Hello, World!"
print(greet()) # デコレートされたgreet関数が実行される
デコレータを使う理由
コードの再利用
デコレータを使うことで、同じ機能を持つコードを複数の関数に適用することができます。これにより、コードの重複を減らし、保守性を向上させることができます。
コードの読みやすさ
デコレータを使うことで、関数の本質的な機能と、その周辺的な機能(例: ロギング、認証など)を分離できます。これにより、コードの可読性が向上し、理解しやすくなります。
デコレータの具体的な使用例
タイミング測定デコレータ
関数の実行時間を計測するデコレータです。関数のパフォーマンスを簡単に確認できます。
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} は実行に {end_time - start_time:.2f} 秒かかりました")
return result
return wrapper
@timing_decorator
def slow_function():
time.sleep(2)
return "終了"
print(slow_function())
#slow_function は実行に 2.00 秒かかりました
#終了
ロギングデコレータ
関数の呼び出しと結果をログに記録するデコレータです。
import logging
def logging_decorator(func):
def wrapper(*args, **kwargs):
logging.info(f"Calling {func.__name__} with arguments {args} and {kwargs}")
result = func(*args, **kwargs)
logging.info(f"{func.__name__} returned {result}")
return result
return wrapper
@logging_decorator
def greet(name):
return f"Hello, {name}!"
print(greet("Alice"))
アクセス制御デコレータ
特定の条件を満たしている場合にのみ、関数を実行できるようにするデコレータです。
def admin_required(func):
def wrapper(*args, **kwargs):
user = kwargs.get("user")
if user and user.get("is_admin"):
return func(*args, **kwargs)
else:
return "アクセスは拒否されました"
return wrapper
@admin_required
def view_secret_data(user):
return f"ユーザー {user['name']} は秘密情報を閲覧しています"
admin_user = {"name": "Alice", "is_admin": True}
regular_user = {"name": "Bob", "is_admin": False}
print(view_secret_data(user=admin_user))
print(view_secret_data(user=regular_user))
#ユーザー Alice は秘密情報を閲覧しています
#アクセスは拒否されました
まとめ
デコレータを使うことで、コードの再利用性や可読性を向上させ、効率的なコードを書くことができます。また、複数のデコレータを組み合わせることで、さまざまな機能を簡単に追加できます。