最近做的项目,由于项目启动时,会去实例化一个类,而这个类初始化会去加载模型,这样导致项目启动的时候特别慢,特别是使用python manage.py *的一些命令时,有时会超时失败,这个时候就想到了懒加载,当真正使用到这个类时,才去初始化这个类。




python 读取usb视频采集数据 python读取obj_网页中加载obj模型比较慢


先来看一下python当中没有使用懒加载的类是怎么初始化的,写这么一类如下:

class LoadModel(object): def __init__(self): print('加载模型开始。。。') print('耗时2分钟。。。。')
 print('加载模型完毕。。。') def tts(self, text): print('合成文本是:%s', text) print('请求模型,文本转语音。。。'
)if __name__ == '__main__': load_model = LoadModel()

运行一下,结果如下:


python 读取usb视频采集数据 python读取obj_python 读取usb视频采集数据_02


可见python中的类实例化时,就进行了初始化,这点和Java中的类的实例化步骤是一样的,但是现在不想去初始化,而是调用里面的tts()方法时再去初始化,再去加载模型。


python 读取usb视频采集数据 python读取obj_懒加载_03


这时我们就要从初始化这块来下手了,可以看出,上面的LoadModel这个类继承了object这个类,这也是和Java中是一样的,继承了父类,父类的实例化机制也就导致了子类的实例化机制,遗传的原因,所以我们去改造父类,这不是说去改造object,这是祖先,不能随便动的,咱们去写一个懒加载的类,然后所有想去懒加载的类,都去继承这个父类,代码如下:

class LazyProxy(object): def __init__(self, cls, *args, **kwargs): self.__dict__['_cls'] = cls self.__dict__['_params'] = args self.__dict__['_kwargs'] = kwargs self.__dict__["_obj"] = None def __getattr__(self, item): if self.__dict__['_obj'] is None: self._init_obj() return getattr(self.__dict__['_obj'], item) def __setattr__(self, key, value): if self.__dict__['_obj'] is None: self._init_obj() setattr(self.__dict__['_obj'], key, value) def _init_obj(self): self.__dict__['_obj'] = object.__new__(self.__dict__['_cls']) self.__dict__['_obj'].__init__(*self.__dict__['_params'], **self.__dict__['_kwargs'])class LazyInit(object): def __new__(cls, *args, **kwargs): return LazyProxy(cls, *args, **kwargs)

想去懒加载的类就去继承LazyInit这个类,从上面代码看,LazyInit这个类实例化时,返回一个LazyProxy对象,而LazyProxy对象初始化时,把_obj对应的字典值设为None,当真正使用的使用,才去调用_init_obj()的方法去初始化这个类,下面代码演示一下:


python 读取usb视频采集数据 python读取obj_懒加载_04


可以看出,当我们实例化LoadModel这个类时,它并没有去初始化,这已经达到目的的一半了,另外一半就是,当我们第一次调用LoadModel中的方法时,它会去初始化吗?答案揭晓如下:


python 读取usb视频采集数据 python读取obj_python 读取usb视频采集数据_05


很显然,初始化了,那么多次调用方法,它会不会多次初始化呢:


python 读取usb视频采集数据 python读取obj_实例化_06


完美,简单的python实例化类的懒加载已经实现了!