我想知道初始化类成员的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类成员延迟初始化
发布评论