---恢复内容开始---
说起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 (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()
---恢复内容结束---