Python

【Python】第3章第8回:デコレータ(decorator)の基礎

本記事では、Pythonのデコレータ(decorator)について解説します。デコレータを使用することで、関数やクラスに追加の機能を簡単に付与できます。Pythonコードをより効率的で再利用可能にしましょう。

0. 記事の概要

この記事を読むメリット

  • デコレータの基本を理解:コードの機能拡張が簡単になります。
  • コードの再利用性向上:同じ処理を繰り返し記述せずに済みます。
  • 実践的な応用力を向上:実用的なデコレータの作成方法を学べます。

この記事で学べること

  • デコレータの基本的な仕組み
  • 組み込みデコレータの使用例
  • 独自デコレータの作成方法

1. デコレータの基本

1.1 デコレータとは?

デコレータとは、関数やメソッドの機能を修飾(装飾)するための関数です。デコレータは、@デコレータ名の形式で使用します。

# デコレータの基本例
def my_decorator(func):
    def wrapper():
        print("処理前")
        func()
        print("処理後")
    return wrapper

@my_decorator
def say_hello():
    print("こんにちは!")

say_hello()
動作解説
  1. @my_decoratorが、say_hello関数を修飾します。
  2. デコレータ内のwrapper関数が、元の関数をラップして実行します。
  3. ラップされた関数の前後に処理が追加されます。

2. デコレータを使った実践例

2.1 実行時間を測定するデコレータ

以下の例では、関数の実行時間を測定するデコレータを作成します。

# 実行時間を測定するデコレータ
import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"実行時間: {end - start:.2f}秒")
        return result
    return wrapper

@timer
def slow_function():
    time.sleep(2)
    print("処理完了!")

slow_function()
動作解説
  1. timerデコレータがslow_functionを修飾します。
  2. 関数の実行前に開始時刻を記録し、実行後に終了時刻を計測します。
  3. 実行時間がprintで出力されます。

2.2 引数をログに記録するデコレータ

以下の例では、関数の引数と戻り値を記録するデコレータを作成します。

# 引数と戻り値をログに記録
def logger(func):
    def wrapper(*args, **kwargs):
        print(f"呼び出し: {func.__name__}({args}, {kwargs})")
        result = func(*args, **kwargs)
        print(f"戻り値: {result}")
        return result
    return wrapper

@logger
def add(a, b):
    return a + b

add(3, 5)
動作解説
  1. loggerデコレータが、関数addを修飾します。
  2. 関数呼び出し時に引数が記録されます。
  3. 戻り値も記録され、結果として出力されます。

3. 組み込みデコレータ

3.1 @staticmethod

@staticmethodは、クラス内で定義された静的メソッドを示します。

# 静的メソッドの使用例
class MyClass:
    @staticmethod
    def greet():
        print("こんにちは、Python!")

MyClass.greet()

3.2 @classmethod

@classmethodは、クラス自身を引数として受け取るメソッドを示します。

# クラスメソッドの使用例
class MyClass:
    value = 0

    @classmethod
    def increment(cls):
        cls.value += 1
        print(f"現在の値: {cls.value}")

MyClass.increment()

4. 練習問題

以下の課題に挑戦してみましょう。

  1. 関数の実行前後に「開始」と「終了」を出力するデコレータを作成してください。
  2. 関数の実行回数を記録するデコレータを作成してください。

5. 練習問題の解答と解説

問1の解答例

# 実行前後にログを出力
def log_execution(func):
    def wrapper(*args, **kwargs):
        print("開始")
        result = func(*args, **kwargs)
        print("終了")
        return result
    return wrapper

@log_execution
def greet():
    print("こんにちは!")

greet()

問2の解答例

# 実行回数を記録
def count_calls(func):
    calls = 0

    def wrapper(*args, **kwargs):
        nonlocal calls
        calls += 1
        print(f"実行回数: {calls}")
        return func(*args, **kwargs)

    return wrapper

@count_calls
def say_hello():
    print("こんにちは!")

say_hello()
say_hello()

6. まとめ

デコレータはPythonの強力な機能の一つで、コードを簡潔かつ効率的に記述するための重要なツールです。ぜひ独自のデコレータを作成して、プログラミングスキルを向上させてください。