django 中的延迟加载技术,python中的lazy技术

---恢复内容开始---

说起lazy_object,首先想到的是django orm中的query_set、fn.Stream这两个类。

query_set只在需要数据库中的数据的时候才 产生db hits。Stream对象只有在用到index时才会去一次次next。

例子:
   f = Stream ()
         fib = f << [ 0 , 1 ] << iters . map ( add , f , iters . drop ( 1 , f ))

 1行生成了斐波那契数列。

说明:

  f是个lazy的对象,f首先放入了0和1,然后放入了迭代器iters.map。等f[2]的时候。就会调用1次next(iters.map(add, f, iters.drop(1, f))),在map的迭代器中,next(f)和next(drop(1,f))被放到add两端。

很高端大气上档次有木有!

这里有个django的lazy的实现代码,

 对象的

#coding: utf-8

#

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__['_params'],

                                             **self.__dict__['_kwargs'])

        self.__dict__['_obj'].__init__(*self.__dict__['_params'],

                                       **self.__dict__['_kwargs'])





class LazyInit(object):



    def __new__(cls, *args, **kwargs):

        return LazyProxy(cls, *args, **kwargs)





class A(LazyInit):



    def __init__(self, x):



        print ("Init A")

        self.x = 14 + x





a = A(1)

print "Go"

print a.x

原理:在类的__new__方法中hook一下,使其返回lazy_proxy 的对象。然后调用__init__方法时,其实就是调用proxy的__init__方法,第一次调用时

也就是当A生成实例时,Proxy才会真正产生一个A的类,并初始化这个类,注意,在这里proxy的init中得到的cls是A而不是Lazy_Init,因为只有A(1)调用时A的__new__才会调用,虽然__new__名字的查找在LazyInit中。


函数的lazy:

""" 

lazy - Decorators and utilities for lazy evaluation in Python 

Alberto Bertogli ([email protected]) 

"""  

  

class _LazyWrapper:  

    """Lazy wrapper class for the decorator defined below. 

    It's closely related so don't use it. 

 

    We don't use a new-style class, otherwise we would have to implement 

    stub methods for __getattribute__, __hash__ and lots of others that 

    are inherited from object by default. This works too and is simple. 

    I'll deal with them when they become mandatory. 

    """  

    def __init__(self, f, args, kwargs):  

        self._override = True  

        self._isset = False  

        self._value = None  

        self._func = f  

        self._args = args  

        self._kwargs = kwargs  

        self._override = False  

  

    def _checkset(self):  

        print '111111111111', self._isset, self._value  

        if not self._isset:  

            self._override = True  

            self._value = self._func(*self._args, **self._kwargs)  

            self._isset = True  

            self._checkset = lambda: True  

            self._override = False  

  

    def __getattr__(self, name):  

        print '----------getattr----',  name  

        if self.__dict__['_override']:  

            return self.__dict__[name]  

        self._checkset()  

        print '@@@@@@@@@', self._value, type(self._value), name, self._value.__getattribute__(name)  

        return self._value.__getattribute__(name)  

  

    def __setattr__(self, name, val):  

        print '----------setattr----',  name, val  

        if name == '_override' or self._override:  

            self.__dict__[name] = val  

            return  

        self._checkset()  

        print '222222222222222'  

        setattr(self._value, name, val)  

        return  

  

def lazy(f):  

    "Lazy evaluation decorator"  

    def newf(*args, **kwargs):  

        return _LazyWrapper(f, args, kwargs)  

  

    return newf  

 

 

@lazy  

def quick_exe():  

    print '---------quick exe-----------'  

    return 'quickquick'  

  

import pdb  

#pdb.set_trace()  

  

quick_exe()  

print '#####################'  

print quick_exe()

 

 

---恢复内容结束---

你可能感兴趣的:(python)