1. はじめに|デコレーターって何?なぜ使うの?
Pythonを学んでいると、こんなコードを見かけたことがありませんか?
@my_decorator
def say_hello():
print("こんにちは!")
この「@」で始まる記述、気になりますよね?
実はこれ、「デコレーター」という仕組みを使って、関数に追加の機能を与えるためのものなんです。
💡 たとえば、こんなときに便利!
想像してみてください。
あなたが作った関数があるとして、その前後に必ずログ(開始・終了のメッセージ)を出したいとします。
でも、関数ごとに毎回こんなコードを書くのはちょっと面倒…
def my_function():
print("処理開始")
# ここが本来の処理
print("処理終了")
そんなときに「デコレーター」が使えると、関数の中身はそのままで、外から機能を付け足すことができます。
@start_end
def my_function():
# ここが本来の処理だけど、装飾される
👀 デコレーターは「関数を装飾する便利ツール」
デコレーター(Decorator)という名前の通り、関数を“飾る”ツールです。
でも、見た目を変えるわけではありません。
関数の動作にちょっとしたプラスαを加えるんです。
✅ この記事では、こんなことがわかります!
このページでは、初心者の方でもしっかり理解できるように、
- デコレーターの仕組みと用途
- 自分で作る方法(中級者への第一歩!)
- 実際のコード例
を、わかりやすく&丁寧に紹介していきます!
「@って何?」と思ったあなたも、この記事を読み終わるころには、自信を持って使えるようになっているはずです😊
さっそく次の章で、デコレーターの基本を見ていきましょう!
2. デコレーターとは?|イメージと基本概念
デコレーターの正体は、ちょっと不思議な**「関数に機能を追加する関数」**です。
でも、「関数に関数を使う」って、ちょっとややこしそう…と思った方もいるかもしれませんね。
大丈夫!ここでは料理やプレゼントの例えを使って、イメージをつかんでいきましょう。
🍰 デコレーターのイメージは「トッピング」や「ラッピング」
デコレーターをイメージで説明すると…
- ケーキにホイップクリームをトッピングする
- プレゼントにリボンをかける
- お弁当にふりかけをかける
こういった「ちょっとしたプラス」を加える感じです。
中身は変わらないけど、見た目や印象が変わる。それがデコレーターの役割です。
🧠 実際には「関数を装飾して、機能をちょい足しする」
具体的には、デコレーターを使うと、関数の前や後に処理を追加することができます。
たとえば、以下のような関数があるとします。
def say_hello():
print("こんにちは!")
このままだと、「こんにちは!」と表示するだけですが、ここにログ出力などを加えたいとき、デコレーターが使えます。
✅ @(アットマーク)で関数に魔法をかける
Pythonでは、関数の上に @デコレーター名 と書くことで、関数に機能を追加できます。
@my_decorator
def say_hello():
print("こんにちは!")
この @my_decorator は、次のように書くのと同じ意味です:
say_hello = my_decorator(say_hello)
つまり、「say_hello関数を、my_decoratorという関数で加工して、置き換える」という動きになります。
💡 よく使われるデコレーターの用途
デコレーターは、以下のような場面でよく使われます。
| 用途 | 説明 |
|---|---|
| ログ出力 | 関数が実行された前後にメッセージを出す |
| 処理時間の計測 | 関数が終わるまでにかかった時間を出す |
| 認証チェック | ユーザーがログインしているか確認する |
| キャッシュ | 関数の結果を一時保存して、無駄な処理を減らす |

このように、関数の中身を変えずに便利な処理を追加できるのが、デコレーターのすごいところなんです!
3. デコレーターを理解する前に知っておきたい3つの基礎知識
デコレーターの正体は「関数に関数を渡して、関数を返す関数」でしたね。
……ちょっと混乱しますよね?😂
でも大丈夫。
ここではデコレーターをしっかり理解するために必要な「3つの基本知識」を、順番にやさしく解説していきます!
① 関数もオブジェクト!変数のように扱える
Pythonでは、「関数も変数と同じように扱えるオブジェクト」です。
つまり、関数を別の関数に渡したり、返したりできるんです。
たとえば、こんなことができます。
def greet():
print("こんにちは!")
say = greet # 関数を変数に代入
say() # 代入した変数を使って関数を呼び出せる
➡ say()を呼ぶと、greet()と同じように動きます。
関数なのに、変数みたいに扱えるって面白いですね!
② 関数の中に関数を書ける(ネスト関数)
Pythonでは、関数の中にもうひとつ関数を書くこともできます。
これを「ネスト関数(入れ子関数)」と呼びます。
def outer():
def inner():
print("これは内側の関数です")
inner() # 外側の関数から内側を呼び出す
outer()
➡ outer()を呼ぶと、inner()が中で実行されます。
これは、デコレーターの仕組みを作るときに欠かせないテクニックなんです!
③ スコープ(変数の見える範囲)を理解しよう
スコープとは「変数がどこから見えるか」というルールのことです。
def outer():
message = "外側の変数"
def inner():
print(message) # 内側から外側の変数にアクセスできる!
inner()
outer()
➡ このコードでは、inner()の中からouter()の変数 message にアクセスしています。
Pythonでは、
- 内側の関数は外側の変数を使える
- 外側の関数は内側の変数を使えない
というルールがあります。
これを理解しておくと、デコレーターのコードがグッと読みやすくなります!
🎓 この3つがわかると、デコレーターも怖くない!
デコレーターでは、
- 関数を変数のように渡したり
- 関数の中で関数を作ったり
- 外側の関数の情報を内側から使ったり

ということをします。
つまり、この3つの知識があれば、**「関数を装飾する関数」**を自分で作れるようになりますよ!
4. デコレーターの作り方|手順とサンプルコード
ここからは、実際にデコレーターを自分で作ってみましょう!
「難しそう…」と思うかもしれませんが、大丈夫。
3ステップで作れるので、順番に見ていけばちゃんと理解できますよ😊
🔧 ステップ① デコレーター関数(外側)を定義する
まずは、デコレーターの「外側の関数」を作ります。
この関数は、「対象となる関数」を引数として受け取るのが特徴です。
def start_end(func):
# ここに次のステップでインナー関数を書くよ
...
ここでの func が、@で装飾される元の関数になります。
🔧 ステップ② インナー関数(内側)を定義する
次に、さっきの関数の中に**「内側の関数」**(=インナー関数)を書きます。
この関数の中で、追加したい処理を書いたり、元の関数 func() を呼び出したりします。
def start_end(func):
def wrapper():
print("=== 処理開始 ===")
func() # 元の関数を実行
print("=== 処理終了 ===")
return wrapper # 最後にこの関数を返す
ここでの wrapper() が、装飾された関数の正体です。
🔧 ステップ③ アットマーク(@)を使って装飾する
さあ、いよいよこのデコレーターを使ってみましょう!
@start_end # これで say_hello を装飾!
def say_hello():
print("こんにちは!")
say_hello()
▶ 出力結果:
=== 処理開始 ===
こんにちは!
=== 処理終了 ===
どうですか?
関数 say_hello() の中はそのままなのに、外側で処理を追加できているのがポイントです!
🧪 まとめ:デコレーターの基本形をおさらい!
def decorator_name(func):
def wrapper():
# ここで前後の処理を追加
func()
# ここで後の処理を追加
return wrapper

このパターンが、デコレーターの「基本形」になります。
このテンプレートを覚えておくと、いろんな場面で応用ができますよ!
5. 可変長引数・戻り値への対応方法
ここからは、もう少し実用的なデコレーターの作り方を紹介します。
さきほどは引数なしの関数を装飾しましたが、実際にはこういう関数も多いですよね?
def greet(name):
print(f"こんにちは、{name}さん!")
このような「引数を受け取る関数」にデコレーターをつけたいとき、どうすればよいのでしょうか?
答えはカンタン!*args と **kwargs を使えばOKです!
✅ 可変長引数 *args と **kwargs って?
*argsは「位置引数」をまとめて受け取るもの(タプルになる)**kwargsは「キーワード引数」をまとめて受け取るもの(辞書になる)
これを使うことで、どんな関数でも柔軟に受け取れるデコレーターが作れるんです!
🔧 実際のコード例
def start_end(func):
def wrapper(*args, **kwargs):
print("=== 処理開始 ===")
result = func(*args, **kwargs) # 元の関数にそのまま引数を渡す
print("=== 処理終了 ===")
return result # 戻り値があるなら、それも返す
return wrapper
このコードでは、
- 任意の引数を
*argsと**kwargsで受け取り - それを元の関数
funcに渡して実行し - 戻り値
resultをそのまま返しています
🧪 これを使って関数を装飾してみよう!
@start_end
def add(a, b):
return a + b
print(add(3, 5)) # => 処理開始〜処理終了のログが出たあと、8と表示される
▶ 出力結果:
=== 処理開始 ===
=== 処理終了 ===
8
add() 関数は「引数あり&戻り値あり」ですが、しっかり動いてますね!
🎁 装飾しても中身の動きはそのまま!
こうすることで、元の関数がどんな引数や戻り値を持っていても対応可能になります。
実際の開発では、ログ記録やバリデーションなどにこの方法がよく使われます。
💡 補足:functools.wraps() を使うとさらに親切
デコレーターを使うと、元の関数の名前やドキュメント文字列が失われてしまいます。
それを防ぐために、Python標準ライブラリの functools.wraps を使うことが多いです。
from functools import wraps
def start_end(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("=== 処理開始 ===")
result = func(*args, **kwargs)
print("=== 処理終了 ===")
return result
return wrapper

こうすることで、__name__ や __doc__ 情報が保たれます。
ちょっと上級ですが、覚えておくとプロっぽいですよ😉
6. 実用例|デコレーターの活用シーン3選
ここでは、実際にどんな場面でデコレーターが使われているかを紹介します。
「ふーん便利そうだけど、いつ使うの?」と思っているあなたに向けて、
現場でよく使われる3つの例を取り上げます!
① ログ出力|処理の開始・終了を表示する
使う理由: デバッグやエラーの原因を特定するために、関数がいつ呼ばれたかを記録しておきたい。
def log_start_end(func):
def wrapper(*args, **kwargs):
print(f"[LOG] {func.__name__} 開始")
result = func(*args, **kwargs)
print(f"[LOG] {func.__name__} 終了")
return result
return wrapper
@log_start_end
def download_file():
print("ファイルをダウンロード中...")
download_file()
▶ 出力例:
[LOG] download_file 開始
ファイルをダウンロード中...
[LOG] download_file 終了
② 認証チェック|ログインしているか確認
使う理由: 関数が実行される前に、ユーザーがログインしているか確認したい。
def login_required(func):
def wrapper(*args, **kwargs):
logged_in = True # 本来はここでログイン状態をチェック
if not logged_in:
print("ログインが必要です!")
return
return func(*args, **kwargs)
return wrapper
@login_required
def view_dashboard():
print("ダッシュボードを表示します")
view_dashboard()
未ログインなら、関数は実行されません。
「共通のチェック処理を一箇所にまとめられる」のが便利!
③ 処理時間の計測|パフォーマンスの確認
使う理由: 処理にどれくらい時間がかかっているかを知りたいとき。
import time
def measure_time(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"処理時間: {end - start:.3f}秒")
return result
return wrapper
@measure_time
def heavy_task():
time.sleep(2) # 時間のかかる処理をシミュレーション
print("重い処理が終わりました")
heavy_task()
▶ 出力例:
重い処理が終わりました
処理時間: 2.002秒
✅ まとめ:デコレーターは「共通処理をまとめて管理」するのが得意!
デコレーターは、関数ごとに何度も同じ処理を書く手間をなくしてくれます。
| シーン | よくある処理 | デコレーターでできること |
|---|---|---|
| ログ記録 | 開始・終了ログを出す | 関数の実行前後に自動追加 |
| 認証 | ログインしてる? | 実行前にチェック |
| パフォーマンス測定 | 時間計測 | 実行時間を自動表示 |
7. まとめ|デコレーターを使ってコードを美しく!
ここまでお疲れさまでした!
「デコレーターってなに?」という疑問から始まり、
仕組み、作り方、応用方法まで、ひと通り理解できたのではないでしょうか?
💡 デコレーターのポイントをおさらい!
- デコレーターとは?
→ 関数に機能を“あとから追加”できる便利な仕組み - なぜ使うの?
→ ログ出力や認証チェックなどの共通処理を1か所にまとめられる! - どう作るの?
→ 「関数を引数にとって、関数を返す関数」を3ステップで定義 - 引数や戻り値は?
→*argsと**kwargsを使えば柔軟に対応できる!
✨ デコレーターを使えば、こんなメリットが!
| メリット | 説明 |
|---|---|
| 再利用性UP | 共通処理をまとめて、何度も使い回せる |
| 可読性UP | 関数の本体はスッキリ!見通しの良いコードに |
| 保守性UP | 修正はデコレーターだけでOK。ミスも減る! |

最初はちょっと難しく感じるかもしれませんが、
**「@を使って関数を飾る」**というイメージがつかめれば、デコレーターはとても便利な道具です。
実際にコードを書いて、自分なりのデコレーターを作ってみましょう!
きっと、「あ、こういうときに使えるかも!」と思える場面が増えてくるはずです。
8. あわせて読みたい
デコレーターの理解をさらに深めたい方や、関連するPythonの基礎をもっと知りたい方に向けて、
ここではおすすめの関連記事をピックアップしました!
どれも初心者向けで、やさしく解説している記事ばかりですので、ぜひあわせてチェックしてみてください😊
📝 【Python入門】引数のデフォルト値とタイプアノテーションの使い方をやさしく解説!
→ デコレーターと一緒によく出てくる「引数の書き方」や「型ヒント」について学べます。
📝 初心者でもすぐわかる!Pythonのクラス入門ガイド|オブジェクト指向をやさしく解説
→ @classmethod や @property など、クラス向けのデコレーターの基礎にもつながる内容です!
📝 Pythonのトレースバック(traceback)の読み方をやさしく解説
→ デコレーターでエラーが起きたときにも役立つ、エラー表示の読み解き方を解説しています。
よくある質問(Q&A)
- Qデコレーターって複数つけても大丈夫なの?
- A
はい、大丈夫です!
デコレーターは1つの関数に何個でも重ねて使うことができます。
書く順番に注意すれば、複数の処理を段階的に追加できます。@decorator_a
@decorator_b
def my_func():
...この場合、
decorator_bが先に適用されてから、decorator_aが適用されます。
「上から順番に魔法をかけていく」イメージですね!
- Qクラスの中でもデコレーターは使えるの?
- A
はい、クラス用のデコレーターもあります!
よく使われるものに次のようなものがあります:
@classmethod:クラス自身を操作するメソッドを定義@staticmethod:クラスに関係ない独立した処理を定義@property:値のように呼べるゲッターを定義(obj.valueみたいに使える)
class Sample:
@property
def name(self):
return "サンプルさん"
- Qデコレーターは使わなくてもいいの?
- A
はい、使わなくてもPythonは書けます!
ただし、以下のような場面ではデコレーターがとっても便利です。
- 同じ処理を何度も書く必要があるとき(ログ出力や認証など)
- 処理の前後に毎回決まったコードを挟みたいとき
- コードをスッキリ保ちたいとき
つまり、「なくても困らないけど、あるとグッと便利」な存在です!







※当サイトはアフィリエイト広告を利用しています。リンクを経由して商品を購入された場合、当サイトに報酬が発生することがあります。
※本記事に記載しているAmazon商品情報(価格、在庫状況、割引、配送条件など)は、執筆時点のAmazon.co.jp上の情報に基づいています。
最新の価格・在庫・配送条件などの詳細は、Amazonの商品ページをご確認ください。