A Python lazy programming library with implicit parallel and otheroptimizations for Functional Programming.
Lazy Evaluation is among useful features in Functional Programming.This tool help make lazy evaluation in Python easier. The expressionis saved in directed graph and evaluated when necessary. The processof evaluation leverage multicore (multiprocessing library in Python)and graph cut algorithm to compute the results in parallel.
- Lazy(func)Return a new lazy function that don't do eager call. Use .eval() tocompute the whole expression in parallel.
- @lazyUseful decorator for function that want to be lazy in definition.
- Lazy.set_cores(num)Set the actual CPU cores in parallel computing. The default value ismultiprocessing.cpu_count()
This example illustrate how to calculateFibnoacci by Lazy Evalution andthe cache mechanism of pure function call with the same parameters. By addingparameter "debug=True", it is easy to show the evaluation process step by step.
>>> from lazy import Lazy>>> lazy_int = Lazy(int, debug=True)>>> def fib(n):... return lazy_int(n) if n <= 1 else fib(n-1) + fib(n-2)... >>> a = fib(10)>>> a(((((((((1+int(0))+1)+(1+int(0)))+((1+int(0))+1))+(((1+int(0))+1)+(1+int(0))))+((((1+int(0))+1)+(1+int(0)))+((1+int(0))+1)))+(((((1+int(0))+1)+(1+int(0)))+((1+int(0))+1))+(((1+int(0))+1)+(1+int(0)))))+((((((1+int(0))+1)+(1+int(0)))+((1+int(0))+1))+(((1+int(0))+1)+(1+int(0))))+((((1+int(0))+1)+(1+int(0)))+((1+int(0))+1))))+(((((((1+int(0))+1)+(1+int(0)))+((1+int(0))+1))+(((1+int(0))+1)+(1+int(0))))+((((1+int(0))+1)+(1+int(0)))+((1+int(0))+1)))+(((((1+int(0))+1)+(1+int(0)))+((1+int(0))+1))+(((1+int(0))+1)+(1+int(0))))))>>> a.eval()int(0) == 0(1+0) == 1(1+1) == 2(2+1) == 3(3+2) == 5(5+3) == 8(8+5) == 13(13+8) == 21(21+13) == 34(34+21) == 5555>>> a55>>> b = fib(11)>>> b(55+34)>>> b.eval()(55+34) == 8989
Lazy Evaluation uses implicit parallel bymultiprocessing. The followingexample shows how the implicit parallel works by using decoratorlazy.
from lazy import lazyimport timedef f(name): print('Enter', name) time.sleep(5) print('Leave', name)@lazydef f1(): f('f1') return 1@lazydef f2(): f('f2') return 2@lazydef f3(): f('f3') return 3@lazydef f4(): f('f4') return 4if __name__ == '__main__': s = f1()*f2()+f3()*f4() print(s) s.eval() print(s)$ time python3 test_parallel.py((f1()*f2())+(f3()*f4()))Enter f1Enter f2Enter f3Enter f4Leave f1Leave f3Leave f4Leave f214real 0m5.173suser 0m0.111ssys 0m0.049s
You can easily change the number of CPU cores in parallel computing by addingLazy.set_cores(num). You can completely disable parallel byLazy.set_cores(0).
$ time python3 test_parallel_with_zero_cores.py((f1()*f2())+(f3()*f4()))Enter f2Leave f2Enter f1Leave f1Enter f3Leave f3Enter f4Leave f414real 0m20.085suser 0m0.055ssys 0m0.016s