アクセスされた場合のみクラス メンバーを初期化する Python の方法を知りたいです。以下のコードを試してみましたが、うまくいきましたが、これよりも簡単な方法はありますか?
class MyClass(object):
_MY_DATA = None
@staticmethod
def _retrieve_my_data():
my_data = ... # costly database call
return my_data
@classmethod
def get_my_data(cls):
if cls._MY_DATA is None:
cls._MY_DATA = MyClass._retrieve_my_data()
return cls._MY_DATA
ベストアンサー1
class MyMetaClass(type):
@property
def my_data(cls):
if getattr(cls, '_MY_DATA', None) is None:
my_data = ... # costly database call
cls._MY_DATA = my_data
return cls._MY_DATA
class MyClass(metaclass=MyMetaClass):
# ...
これにより、my_data
クラスに属性が作成され、高価なデータベース呼び出しは、アクセスしようとするまで延期されますMyClass.my_data
。データベース呼び出しの結果は、に格納されてキャッシュされMyClass._MY_DATA
、呼び出しは一度クラスのために。
Python 2の場合はclass MyClass(object):
、__metaclass__ = MyMetaClass
属性クラス定義本体にメタクラスを添付します。
デモ:
>>> class MyMetaClass(type):
... @property
... def my_data(cls):
... if getattr(cls, '_MY_DATA', None) is None:
... print("costly database call executing")
... my_data = 'bar'
... cls._MY_DATA = my_data
... return cls._MY_DATA
...
>>> class MyClass(metaclass=MyMetaClass):
... pass
...
>>> MyClass.my_data
costly database call executing
'bar'
>>> MyClass.my_data
'bar'
これが機能するのは、 のようなデータ記述子property
がオブジェクトの親タイプで検索されるためです。 であるクラスの場合type
、 はtype
メタクラスを使用して拡張できます。