PYTHON MEBY

Pythonでfunctools.cached_property を使ってキャッシュプロパティを定義 (Python 3.8以降)

この記事では、Python 3.8以降で導入されたfunctools.cached_propertyデコレータを使用して、プロパティの値をキャッシュする方法について説明します。パフォーマンスの最適化に役立つこのテクニックを、具体的な例を通して学びます。

目次

cached_propertyの概要

functools.cached_propertyは、プロパティの値を一度計算したらキャッシュし、次回以降はキャッシュされた値を返すデコレータです。プロパティの計算に時間がかかる場合や、同じ値が何度も必要となる場合に、パフォーマンスを大幅に向上させることができます。

Python 3.8以降で標準ライブラリに含まれています。

from functools import cached_property

class MyClass:
    def __init__(self, value):
        self._value = value

    @cached_property
    def expensive_property(self):
        print("expensive_property is calculated...")
        # 計算コストの高い処理
        return self._value * 2

基本的な使用方法

cached_propertyデコレータをメソッドの前に付けるだけです。

from functools import cached_property

class MyClass:
    @cached_property
    def my_property(self):
        return 'Hello, cached_property!'

利点と注意点

利点

  • プロパティの値をキャッシュすることで、計算コストの高い処理を何度も実行する必要がなくなり、パフォーマンスが向上する。
  • 一度計算された値は、インスタンスのライフサイクルの間、キャッシュされる。

注意点

  • プロパティの値が変更される可能性がある場合は、注意が必要。キャッシュされた値が古くなる可能性がある。
  • キャッシュされた値は、インスタンスのライフサイクルの間、常に同じ値となる。値を変更したい場合は、@propertyとsetterメソッドを組み合わせる必要がある。
  • あまりにも頻繁にアクセスするプロパティには、別のキャッシュメカニズム(例えば、`lru_cache`)の方が効率的である可能性がある。

実践例:ファイル読み込み

大きなファイルを読み込むプロパティを定義してみましょう。

import os
from functools import cached_property

class FileProcessor:
    def __init__(self, filepath):
        self.filepath = filepath

    @cached_property
    def file_content(self):
        print(f"Reading file: {self.filepath}")
        with open(self.filepath, 'r') as f:
            return f.read()

# テスト
filepath = 'my_file.txt'
with open(filepath, 'w') as f:
    f.write('This is a test file.')

processor = FileProcessor(filepath)
print(processor.file_content)
print(processor.file_content) # キャッシュされた値が返される

上記のように、ファイルを読み込む処理は一度だけ実行され、2回目のアクセスではキャッシュされた値が返されます。ファイルサイズが大きい場合、この効果は顕著に現れます。

関連記事