【Python】デコレータ徹底解説|基礎からわかりやすく解説!

【Python】デコレータ徹底解説|基礎からわかりやすく解説!

Amazonのアソシエイトとして、ITナレッジライフは適格販売により収入を得ています。

記事の文字数:1,430 / 総アクセス数:241 views

Pythonのデコレータは、関数やクラスの振る舞いを柔軟に拡張できる便利な機能です。本記事では、初心者でも理解しやすいコード例と実行結果を交えて、デコレータの基本的な仕組みから、実践的な応用例まで詳しく解説します。Pythonの開発を効率化し、可読性の高いコードを書けるようになりましょう!

Pythonのデコレータ(Decorator)は、関数やクラスの振る舞いを変更するための機能です。デコレータを使うことで、コードの再利用性を高め、簡潔かつ直感的な記述が可能になります。
本記事ではデコレータの基本的な使い方から関数やクラスへの適用方法、可変長引数への適用など詳しく解説します。またログの記録や実行時間の計測、認証といった応用的な実装例も紹介します。

デコレータの基本的な使い方

デコレータは、関数を引数として受け取り、新しい関数を返す高階関数です。デコレータを利用することで、関数の振る舞いを変更することができます。
デコレータは関数名の前に@デコレータ名という形で指定して利用します。
基本的なデコレータの使い方を見てみましょう。

デコレータの実装例

以下は処理の前後で処理開始、処理終了を出力するデコレータです。

decorator-ex-01.py
# デコレータの定義
def my_decorator(func):
def wrapper():
print("処理開始")
func()
print("処理終了")
return wrapper
# デコレータを適用
@my_decorator
def my_function():
print("メインの処理")
my_function()

上記、10行目で @my_decorator を指定し、my_functionを引数として渡します。

デコレータの実行結果

実行結果
$ python decorator-ex-01.py
処理開始
メインの処理
処理終了

上記の通り、my_function関数の前後で、処理開始・処理終了の追加の処理が実行されることを確認できました。

デコレータの応用的な使い方

デコレータは、関数の前後に特定の処理を挿入するのに便利で、例えばログの記録、実行時間の計測、認証のチェックなどに活用されます。また、コードの可読性を向上させる役割も果たします。

引数を持つ関数にデコレータを適用

デコレータを適用する関数が引数を取る場合、*args**kwargs を使用して可変長引数に対応できます。これにより、どんな関数にも柔軟に適用可能になります。

decorator-ex-02.py
def my_decorator(func):
def wrapper(*args, **kwargs):
print("処理開始")
result = func(*args, **kwargs)
print(result)
print("処理終了")
return result
return wrapper
@my_decorator
def add(a, b):
return a + b
add(3, 5)

処理開始と処理終了の間でadd関数の結果(3+5=8)が表示されることを確認できました。

実行結果
$ python decorator-ex-02.py
処理開始
8
処理終了

複数のデコレータを適用

複数のデコレータを組み合わせることで、関数に複数の装飾を適用できます。

decorator-ex-03.py
def decorator1(func):
def wrapper(*args, **kwargs):
print("デコレータ1実行")
return func(*args, **kwargs)
return wrapper
def decorator2(func):
def wrapper(*args, **kwargs):
print("デコレータ2実行")
return func(*args, **kwargs)
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()

以下の通り、デコレータは上から順に適用されます。

実行結果
python decorator-ex-03.py
デコレータ1実行
デコレータ2実行
Hello!

デコレータをクラスに適用する

デコレータはクラスにも適用でき、クラスの振る舞いを変更できます。

decorator-ex-04.py
def class_decorator(cls):
class NewClass(cls):
def new_method(self):
return "追加メソッド"
return NewClass
@class_decorator
class MyClass:
def original_method(self):
return "元のメソッド"
obj = MyClass()
print(obj.original_method())
print(obj.new_method())

元のメソッドに加えて、追加メソッドの実行ができるようになります。

実行結果
python decorator-ex-04.py
元のメソッド
追加メソッド

デコレータの様々な実用例

デコレータでロギングを行う

デコレータを使って関数の実行ログを記録し、デバッグや動作確認に役立てることができます。

decorator-ex-05.py
import functools
def log_decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
print(f"関数 {func.__name__} を実行します")
return func(*args, **kwargs)
return wrapper
@log_decorator
def greet(name):
print(f"こんにちは、{name}!")
greet("太郎")

以下の通り、こんにちは、太郎!の前に開始ログが出力されます。

実行結果
python decorator-ex-05.py
関数 greet を実行します
こんにちは、太郎!

デコレータで実行時間を計測する

関数の実行時間を計測するデコレータの例です。処理のパフォーマンス測定に利用することができます。

decorator-ex-06.py
import time
def timer_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"実行時間: {end_time - start_time} 秒")
return result
return wrapper
@timer_decorator
def slow_function():
time.sleep(2)
print("処理が完了しました")
slow_function()
実行結果
python decorator-ex-06.py
処理が完了しました
実行時間: 2.0016653537750244

デコレータでキャッシュを利用する

functools.lru_cache を利用して関数の結果をキャッシュし、パフォーマンスを向上させることができます。

decorator-ex-07.py
from functools import lru_cache
@lru_cache(maxsize=5)
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
実行結果
python decorator-ex-07.py
55

デコレータで認証を行う

認証処理を簡単に追加できます。以下例ではadminユーザのみ許可しています。

decorator-ex-08.py
def auth_decorator(func):
def wrapper(user):
if user != "admin":
print("アクセス拒否")
return
return func(user)
return wrapper
@auth_decorator
def secret_function(user):
print("機密情報を表示")
print("▼guestの場合")
secret_function("guest")
print("▼adminの場合")
secret_function("admin")
実行結果
python decorator-ex-08.py
▼guestの場合
アクセス拒否
▼adminの場合
機密情報を表示

シングルトンをデコレータで実装する

シングルトンパターンを実装し、インスタンスの重複生成を防ぎます。

decorator-ex-10.py
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
def __init__(self):
print("データベース接続")
db1 = Database()
db2 = Database()
print(db1 is db2) # True
実行結果
python decorator-ex-09.py
データベース接続
True

デコレータまとめ

  • デコレータは@デコレータ名で指定する。
  • デコレータは関数やクラスに指定できる。
  • デコレータを適用する関数が引数を取る場合、*args**kwargsを使用して可変長引数に対応できる。
  • デコレータを利用することでログの記録、実行時間の計測、認証のチェックなどに活用できる。

デコレータを活用すると、コードの再利用性が向上し、保守性が向上します。
デコレータは便利なツールであり、さまざまな場面で活用できます。上手に使いこなし、より効率的なコードを書けるようになりましょう!

Pythonユーザにお勧めの本

人気

スッキリわかるPython入門 第2版 スッキリわかるシリーズ

難易度
実用性
読みやすさ

対話形式でスラスラ読める。複雑な概念もキャラクターが分かりやすく解説してくれます。

独習Python

難易度
実用性
網羅性

言語仕様を深く解説。なんとなく書ける状態から、自信を持って書ける状態へ引き上げてくれます。

Python1年生 第2版 体験してわかる!会話でまなべる!プログラミングのしくみ

難易度
実用性
読みやすさ

イラスト中心で、プログラミングの楽しさを教えてくれる。ワクワクしながら学べる入門書です。


以上で本記事の解説を終わります。
よいITライフを!

Pythonユーザにお勧めの本

人気

スッキリわかるPython入門 第2版 スッキリわかるシリーズ

難易度
実用性
読みやすさ

対話形式でスラスラ読める。複雑な概念もキャラクターが分かりやすく解説してくれます。

人気記事


記事を評価

Thanks!
目次
Scroll to Top