6.1 クラスメソッドのためのデコレーター
デコレーターはクラスメソッドにも使えるんだ。大事なのは、クラスメソッド用に selfかclsという引数を正しく渡すことだね。
クラスの動作についてはまだ勉強していないけど、デコレーターにはこんな機能もあるって知っておいてほしいな。
def log_method_call(func):
def wrapper(self, *args, **kwargs):
print(f"メソッド {func.__name__} の呼び出し")
return func(self, *args, **kwargs)
return wrapper
class MyClass:
@log_method_call
def say_hello(self):
print("Hello from MyClass!")
obj = MyClass()
obj.say_hello()
説明
デコレーター (log_method_call): このデコレーターはメソッド funcを受け取って、メソッドの呼び出し前にメッセージを出力する新しい関数wrapperを返すんだ。
デコレーター付きクラスメソッド (say_hello): メソッドsay_helloはデコレーターlog_method_callでラップされて、呼び出し時の追加の動作をするんだ。
出力:
メソッド say_hello の呼び出し
Hello from MyClass!
6.2 複数のデコレーター
1つの関数に複数のデコレーターを重ねて使うことができるよ。デコレーターは宣言された順とは逆の順序で適用されるんだ。
def decorator1(func):
def wrapper():
print("デコレーター 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("デコレーター 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()
説明
デコレーター (decorator1 と decorator2): これらのデコレーターは関数funcの呼び出し前にメッセージを追加するんだ。
デコレーター付き関数 (say_hello): 関数say_helloは両方のデコレーターでラップされているよ。最初にdecorator2が適用されて、その後にdecorator1が適用されるんだ。
出力:
# デコレーター 1
# デコレーター 2
Hello!
6.3 組み込みデコレーター
Pythonには、静的メソッド、クラスメソッド、プロパティなどの標準的なタスクのためのいくつかの組み込みデコレーターがあるよ。
@staticmethod
@staticmethodデコレーターは、クラスのインスタンスを必要とせずに呼び出せる静的メソッドを作成するために使われるんだ。
class MyClass:
@staticmethod
def static_method():
print("これは静的メソッドです。")
MyClass.static_method()
@classmethod
@classmethodデコレーターは、クラス(インスタンスではなく)を最初の引数として受け取るクラスメソッドを作成するために使われるんだ。
class MyClass:
@classmethod
def class_method(cls):
print(f"これはクラスメソッド {cls.__name__} です。")
MyClass.class_method()
@property
@propertyデコレーターは、属性のゲッター、セッター、デリーターを作成するために使われるんだ。
class MyClass:
def __init__(self, value):
self.hidden_value = value
@property
def value(self):
return self.hidden_value
@value.setter
def value(self, new_value):
self.hidden_value = new_value
obj = MyClass(10)
print(obj.value) # 出力: 10
obj.value = 20
print(obj.value) # 出力: 20
これらは組み込みデコレーターで、Pythonのインタプリタがその正しい動作を保証しているんだ。
6.4 デコレーターの使用例
ログ
デコレーターは、関数やメソッドの呼び出しをログに記録するために使われることがあるよ。
def log_call(func):
def wrapper(*args, **kwargs):
print(f"関数 {func.__name__} の呼び出し 引数 {args} と {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_call
def add(x, y):
return x + y
print(add(2, 3))
アクセス制御
デコレーターは、関数やメソッドへのアクセス制御のために使われることがあるよ。
def require_authentication(func):
def wrapper(*args, **kwargs):
if not args[0].is_authenticated:
raise PermissionError("ユーザーが認証されていません。")
return func(*args, **kwargs)
return wrapper
class User:
def __init__(self, is_authenticated):
self.is_authenticated = is_authenticated
@require_authentication
def view_profile(self):
print("ユーザープロファイル")
user = User(is_authenticated=True)
user.view_profile() # 成功した呼び出し
user2 = User(is_authenticated=False)
user2.view_profile() # PermissionError: ユーザーが認証されていません。
キャッシュ
デコレーターは、関数の結果をキャッシュするために使われることがあるよ。
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
@cache
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(35))
GO TO FULL VERSION