在Python里實現Lazy

為了在flowpython里實現lazy,在某位的建議下,我先用原生的Python(雖然混雜了一丁點flowpython語法)探究了一下實現思路。

定義如下,一目了然。

import inspectndef checker(func):n def _f(self,*args,**kwargs):n if self.on:n ret = func(self,*args,*kwargs)n self.on = Falsen return retn else:n raise ValueError("lazy value has been evaluated twice!!!")n return _fnclass Addable:n @checkern def __add__(self,v):n return next(self.obj)()+vn @checkern def __radd__(self,v):n return v + next(self.obj)()nclass Multable:n @checkern def __mul__(self,v):n return next(self.obj)()*vn @checkern def __rmul__(self,v):n return v * next(self.obj)()nnclass Subable:n @checkern def __sub__(self,v):n return next(self.obj)() - vn @checkern def __rsub__(self,v):n return v - next(self.obj)()nnclass Divable:n @checkern def __truediv__(self,v):n return next(self.obj)() / vn @checkern def __rtruediv__(self,v):n return v / next(self.obj)()ndef lazy(*args):n class _lazy(*args):n def __init__(self, obj):n if inspect.getargs(obj.__code__) -> _.args or _.varargs or _.varkw:n raise ValueError("not suitable for lazy definitions")n self.obj = iter((obj,))n self.on = Truen return _lazyn

然後看一下效果。

看一下定義lazy的速度

好吧,辣雞python,我們舉數據量大一點的例子。

感覺得數據量非常大的時候才有用...

模擬一個lazy實在是開銷很大的事情。

而且這個lazy很蠢啊,比如range可以生成生成器,這種也很lazy,但是上面這些東西和它似乎沒什麼關係。

a = [1..]na!!100n

這個還得專門寫一下

class Indexable:n def __getitem__(self,v):n n = self.num_evaln if v >= n:n for i in range(n, v+1):n self.evaluated[i] = next(self.obj)n self.num_eval += v+1 -nn return self.evaluated[v]nnclass Iterable:n def __iter__(self):n if self.end == self.num_eval:n yield from self.evaluatedn if self.end > self.num_eval:n for i in range(self.num_eval):n yield self.evaluated[i]n for i in range(self.num_eval, self.end):n self.evaluated[i] = next(self.obj)n yield self.evaluated[i]n self.num_eval = self.endnnndef lazyIter(*args):n class _lazy(*args):n def __init__(self,obj):n try:n if not inspect.isgenerator(obj):n obj_gen = (i for i in obj)n else:n obj_gen = objn except:n raise ValueError("not suitable for lazy definitions")n self.obj = obj_gen n self.end = len(obj)n self.evaluated = [ None for i in range(self.end) ]n self.num_eval = 0n self.on = Truen return _lazyn

效果是這樣

講真我覺得這個不Python。

啊,應該怎麼合適的實現lazy呢。

難道需要任何屬性都得說明一下么。。

怕不是我要用個lazy的list得這樣。

lazyIter(Indexable,Iterable,xxxable,...)(range(100))n

Haskell那種原生支持好像挺難辦的。人家速度還飛快。

看起來從語言層面實現方便而不低效的lazy還任重道遠。

推薦閱讀:

黃哥Python提醒:是誰給你的勇氣,你想從事大數據方面工作?
Python 會不會替代 MATLAB?
Python 里為什麼函數可以返回一個函數內部定義的函數?
[9] Python句式特徵
tornado為什麼使用epoll的水平觸發模式,而不是邊緣觸發模式?

TAG:Python | 设计模式 |