---恢復內容開始---數據庫
提及lazy_object,首先想到的是django orm中的query_set、fn.Stream這兩個類。django
query_set只在須要數據庫中的數據的時候才 產生db hits。Stream對象只有在用到index時纔會去一次次next。app
1行生成了斐波那契數列。ide
說明:函數
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兩端。ui
很高端大氣上檔次有木有!lua
這裏有個django的lazy的實現代碼,spa
對象的code
#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__方法,第一次調用時orm
也就是當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 (albertito@blitiri.com.ar) """ 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()
---恢復內容結束---