5
6

Python デコレータを使って関数をパワーアップする方法

Posted at

はじめに

Pythonのデコレータは、既存の関数やクラスを修正したり拡張したりする強力な機能です。本記事では、デコレータの基本的な概念から実践的な使用例まで、段階的に解説していきます。

デコレータとは

デコレータは、他の関数を引数として受け取り、その動作を変更または拡張する関数です。簡単に言えば、既存の関数をラップして新しい機能を追加する方法です。

image.png

基本的なデコレータの書き方

まずは、シンプルなデコレータの例を見てみましょう。

def simple_decorator(func):
    def wrapper():
        print("関数が呼び出される前")
        func()
        print("関数が呼び出された後")
    return wrapper

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

say_hello()

実行結果:

関数が呼び出される前
こんにちは!
関数が呼び出された後

この例では、simple_decoratorsay_hello関数をラップし、関数の前後に追加のメッセージを表示します。

引数を持つ関数のデコレート

引数を持つ関数にデコレータを適用する場合は、以下のように書きます。

def log_args(func):
    def wrapper(*args, **kwargs):
        print(f"呼び出された引数: {args}, {kwargs}")
        return func(*args, **kwargs)
    return wrapper

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

result = add(3, 5)
print(f"結果: {result}")

実行結果:

呼び出された引数: (3, 5), {}
結果: 8

この例では、log_argsデコレータが関数の引数をログ出力します。

デコレータに引数を渡す

デコレータ自体に引数を渡したい場合は、以下のように実装します。

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(times=3)
def greet(name):
    print(f"こんにちは、{name}さん!")

greet("太郎")

実行結果:

こんにちは、太郎さん!
こんにちは、太郎さん!
こんにちは、太郎さん!

この例では、repeatデコレータが関数を指定回数繰り返し実行します。

実践的な使用例

1. 実行時間の計測

import time

def measure_time(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:.4f}")
        return result
    return wrapper

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

slow_function()

実行結果:

処理完了
slow_functionの実行時間: 2.0021秒

2. キャッシュ(メモ化)

def memoize(func):
    cache = {}
    def wrapper(*args):
        if args in cache:
            return cache[args]
        result = func(*args)
        cache[args] = result
        return result
    return wrapper

@memoize
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(100))

実行結果:

354224848179261915075

この結果は瞬時に出力されます。キャッシュがない場合、この計算には非常に長い時間がかかります。

まとめ

デコレータを使うことで、コードの再利用性が高まり、関数の機能を柔軟に拡張できます。本記事で紹介した例を参考に、自分のプロジェクトでデコレータを活用してみてください。デバッグ、ログ出力、性能測定など、様々な場面でデコレータが役立つはずです。

image.png

参考文献

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6