はじめに
このシリーズでは、Python 初心者にもわかりやすく「便利なデコレータ」の使い方を毎回1つずつ紹介していきます。
💡「そもそもデコレータって何?」という方は、まず以下の記事をご覧ください:
今回は、@lru_cache というデコレータを紹介します。
🗣 読み方は「エルアールユーキャッシュ」と読みます。
これは、関数の処理結果を自動的にキャッシュして再利用するという、とても実用的なデコレータです。
💡 キャッシュとは「一回やったことを一時的に覚えておいて、次はサボる」仕組みです。
「同じ関数を何度も呼び出すと毎回時間がかかる…」
そんなときに @lru_cache を使えば、2回目以降の処理を一瞬に高速化できます。
特に以下のような場面で役立ちます:
- 再帰関数の高速化
- APIレスポンスや重い計算処理のキャッシュ
- データ処理系スクリプトのパフォーマンス改善
使い方はとてもシンプルで、関数に1行追加するだけ!
ではさっそく、@lru_cache の魅力を実例とともに見ていきましょう。
🔰 基本の使い方
@lru_cache を使うには、Pythonの標準ライブラリ functools をインポートして、関数の上に @lru_cache をつけるだけです。
今回はわかりやすい例として「フィボナッチ数列」を題材に、@lru_cache を使った場合と使わなかった場合の処理時間を比較してみましょう。
@lru_cache なし(毎回計算)
import time
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
start = time.time()
print(fib(40))
print(f"実行時間: {time.time() - start:.2f}秒")
結果
102334155
実行時間: 16.56秒
import time
from functools import lru_cache
@lru_cache()
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
start = time.time()
print(fib(35))
print(f"実行時間: {time.time() - start:.2f}秒")
出力
102334155
実行時間: 0.00秒
実行時間が「0.00秒」と表示されるのは、めちゃくちゃ速すぎて秒単位では測れなかっただけです(本当に0ではありません)
time.perf_counter() でより正確に測りました。
102334155
実行時間: 0.000040秒
早すぎる....
⚙️ どうやってキャッシュされているの?
@lru_cache を使うと、関数に渡された「入力」と「答え」をセットで覚えてくれるようになります。
そして、まったく同じ入力でもう一度呼ばれたときは、前に出した答えをパッと取り出してくれるので、計算し直さずにすぐに結果が返ってきます。
たとえば以下のような流れで処理されています:
fib(5) を呼び出す
└→ fib(4) + fib(3)
└→ fib(3) + fib(2)
└→ fib(2) + fib(1)
...(どんどん再帰)...
一度計算された fib(3) や fib(2) は、2回目以降はキャッシュから即返される!
📊 キャッシュの中身を見てみよう:cache_info()
@lru_cache を使っているとき、どれだけキャッシュが使われたかを確認できる便利なメソッドcache_infoがあります。
cache_infoを使って中身を確認してみます。
from functools import lru_cache
@lru_cache()
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
fib(40)
print(fib.cache_info())
出力
CacheInfo(hits=38, misses=41, maxsize=128, currsize=41)
| 項目 | 意味 |
|---|---|
| hits | キャッシュから値が返された回数 |
| misses | 計算が必要だった回数(=初回やキャッシュ外) |
| maxsize | キャッシュの最大保存数 |
| currsize | 現在キャッシュに保存されている件数 |
上記の例だと計算回数が41回必要で、そのうち38がキャッシュから返却されていることがわかります。
💡 hits が多いほどキャッシュがうまく活用されている証拠です。
🎛 キャッシュの最大保存数を変える:maxsize
デフォルトでは、キャッシュできる件数は最大128個ですが、@lru_cache(maxsize=◯◯) で変更できます。
1000にする場合
@lru_cache(maxsize=1000)
保存件数を 無制限にしたい場合は、None
@lru_cache(maxsize=None)
⚠️ただし、無制限にすると メモリをたくさん使ってしまう可能性があるので注意です。
@lru_cacheは「LRU(Least Recently Used)」方式を採用しているので、
maxsize を超えた分は自動的にキャッシュから削除されます。
📝 終わりに
今回は、@lru_cache というデコレータを使って、関数の結果をキャッシュして処理を高速化する方法を紹介しました。
たった1行追加するだけで、重たい計算が一気に高速化されるのは本当に驚きです。
ぜひ皆さんも試してみてください!