Python类成员延迟初始化 [英] Python class member lazy initialization

查看:105
本文介绍了Python类成员延迟初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道初始化类成员的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆