デコレータ

関数の動作を変更するための構文。

デコレータ
関数の動作を変更するための構文。
ラッパー関数
デコレータで作成される内側の関数。
プロパティ
属性のようにアクセスできるメソッド。
静的メソッド
クラスから呼び出せるメソッド。
クラスメソッド
インスタンスから呼び出せるメソッド。

デコレータの基本

ラッピング

デコレータは「ラッピング」のようなもの。関数を別の関数で包み、実行前後に追加の処理を加えます。これにより、関数の動作を変更できます。

なぜデコレータが必要か?

デコレータは、関数の動作を変更するのに適しています。特に、ロギング、キャッシング、認証などの横断関心事を追加する場合に有効です。

いつ使うか?

  • ロギングを追加する場合
  • キャッシングを追加する場合
  • 認証を追加する場合
  • メトリクスを収集する場合

実践テクニック

functools.wrapsを使う

functools.wrapsを使うことで、デコレータを簡潔に記述できます。これにより、デコレータの可読性を向上できます。

@wrapsを使う

@wrapsを使うことで、デコレータをより簡潔に記述できます。これはPython 3.4以降で利用可能です。

Decorator Basics
# デコレータの基本
import functools
def my_decorator(func):
def wrapper():
print("Before function call")
result = func()
print("After function call")
return result
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()

引数付きデコレータ

パラメータ付きラッピング

引数付きデコレータは「パラメータ付きラッピング」のようなもの。デコレータに引数を渡すことで、デコレータの動作をカスタマイズできます。

なぜ引数付きデコレータが必要か?

引数付きデコレータは、デコレータの動作をカスタマイズするのに適しています。特に、再試行回数を指定したり、キャッシュキーを設定したりする場合に有効です。

いつ使うか?

  • デコレータにパラメータを渡す場合
  • デコレータの動作をカスタマイズする場合
  • 再試行ロジックを実装する場合

実践テクニック

デコレータファクトリを使う

デコレータファクトリを使うことで、引数付きデコレータを作成できます。これは、デコレータを返す関数のことです。

デコレータをスタックする

デコレータをスタックすることで、複数のデコレータを同時に適用できます。これにより、複雑な動作を簡潔に記述できます。

Decorators with Arguments
# 引数付きデコレータ
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")

組み込みデコレータ

標準装備のラッピング

組み込みデコレータは「標準装備のラッピング」のようなもの。Python標準で提供されるデコレータを使うことで、追加のインストールなしで機能を利用できます。

なぜ組み込みデコレータが必要か?

組み込みデコレータは、標準機能を利用するのに適しています。追加のインストールなしで、すぐに使用できます。

いつ使うか?

  • プロパティを作成する場合
  • 静的メソッドを作成する場合
  • クラスメソッドを作成する場合
  • 抽象クラスを作成する場合

実践テクニック

@propertyを使う

@propertyを使うことで、ゲッターとセッターを実装できます。これにより、属性アクセス時に検証や計算を追加できます。

@staticmethodと@classmethodを使い分ける

@staticmethodはクラスから直接呼び出せるメソッド、@classmethodはクラス(最初の引数)を渡すメソッドです。適切に使い分ける必要があります。

Built-in Decorators
# 組み込みデコレータ
import functools
class MyClass:
@property
def my_property(self):
return self._value
def __init__(self):
self._value = 42
obj = MyClass()
print(obj.my_property)

使用例

デコレータの実際の使用例を確認する。

Use Cases
# デコレータの使用例
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} took {end_time - start_time:.4f} seconds")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
return "Done"
result = slow_function()

合格ライン

デコレータを作成できる
引数付きデコレータを作成できる
組み込みデコレータを使用できる
デコレータの使い分けができる

演習課題

課題1: デコレータの作成
デコレータを作成し、関数の実行前後にメッセージを表示してください。
課題2: 引数付きデコレータの作成
引数付きデコレータを作成し、関数を複数回実行してください。
課題3: @propertyの使用
@propertyを使って、ゲッターとセッターを実装してください。

参考文献

この記事は以下の公的ガイドライン/標準に基づいています。