---恢复内容开始---
说起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‘] = kwargsself.__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 + xa = 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 = Falsedef _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 = Falsedef __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)
returndef 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()
---恢复内容结束---
django 中的延迟加载技术,python中的lazy技术,码迷,mamicode.com