Python类成员延迟初始化 [英] Python class member lazy initialization
问题描述
我想知道初始化类成员的python方法是什么,但是只有在访问它时(如果被访问). 我尝试了下面的代码,并且可以正常工作,但是有比这更简单的东西吗?
I would like to know what is the python way of initializing a class member but only when accessing it, if accessed. I tried the code below and it is working but is there something simpler than that?
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
推荐答案
您可以使用元类上的@property
>代替:
You could use a @property
on the metaclass instead:
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
中来对其进行缓存,该调用仅在该类上一次一次进行.
This makes my_data
an attribute on the class, so the expensive database call is postponed until you try to access MyClass.my_data
. The result of the database call is cached by storing it in MyClass._MY_DATA
, the call is only made once for the class.
对于Python 2,使用class MyClass(object):
并添加 __metaclass__ = MyMetaClass
属性在类定义主体中以附加元类.
For Python 2, use class MyClass(object):
and add a __metaclass__ = MyMetaClass
attribute in the class definition body to attach the metaclass.
演示:
>>> 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
可以通过使用元类进行扩展.
This works because a data descriptor like property
is looked up on the parent type of an object; for classes that's type
, and type
can be extended by using metaclasses.
这篇关于Python类成员延迟初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!