Package: lazystream
Lazy StreamLazy Stream is a library for lazy evaluation in Python, inspired by the Scala Stream class.Lazy Stream allows you to store and chain operations on a finite or infinite sequence of values. The final result will only be computed when needed, for better memory and performance over conventional Python lists.InstallationLazy Stream can be installed via pip:pipinstalllazystreamUsageLazy Stream supports basic stream operations and parallelism. Below is a quick overview of the current features. Feel free to request additional features.CreationLazy Stream is very easy to use. You can create a stream from any function or iterator and obtain the results viaevaluate. Finite and infinite streams are supported, but care must be taken when using infinite streams to avoid infinite operation.fromlazystreamimportLazyStream# Finite stream from iteratorincremental_stream=LazyStream.from_iterator(iter(range(5)))incremental_stream.evaluate()# [0, 1, 2, 3, 4]deffibonacci():a,b=0,1whileTrue:yieldaa,b=b,a+b# Infinite stream from function-defined iteratorfibo_stream=LazyStream.from_iterator(fibonacci())fibo_stream.evaluate(5)# [0, 1, 1, 2, 3]fibo_stream.evaluate()# Unsafe, will never terminateYou can also create a stream from a function, which will be evaluated lazily:importrandomfromlazystreamimportLazyStream# Infinite streams from functionrandom_stream=LazyStream.from_lambda(lambda:random.randint(0,100))OperationsYou can chain operations on streams, which will be evaluated lazily. Classic stream-compatible operations are supported, such asmapandfilter. Non-stream-compatible operations are not supported and should be done after evaluation.fromlazystreamimportLazyStreamstream=LazyStream.from_iterator(iter(range(10)))stream.filter(lambdax:x%2==0).map(lambdax:x*2).evaluate()# [0, 4, 8, 12, 16]EvaluationYou can obtain the results of a stream as a list viaevaluate, which allows you to optionally set a limit on the number of elements to evaluate. This is useful/required for infinite streams.fromlazystreamimportLazyStreamstream=LazyStream.from_lambda(lambda:1)stream.evaluate(5)# [1, 1, 1, 1, 1]You can also use the stream as an iterator itself. Note that proper termination conditions must be set for infinite streams.importrandomfromlazystreamimportLazyStream# Iterate on a finite streamfinite_stream=LazyStream.from_iterator(iter(range(10)))forxinfinite_stream:print(x)# Iterate on an infinite streaminfinite_stream=LazyStream.from_lambda(lambda:random.randint(0,1))forxininfinite_stream:print(x)ifx==1:breakIn addition, thereduceoperation is supported, which allows you to obtain a single value from a stream.fromlazystreamimportLazyStream# Reduce on a finite streamstream=LazyStream.from_iterator(iter(range(10)))stream.reduce(lambdax,y:x+y,accum=0)# 45# Reduce on an infinite streamstream=LazyStream.from_lambda(lambda:1)stream.reduce(lambdax,y:x+y,accum=0,limit=5)# 5ParallelismYou can add parallelism to the stream via functional mappingpar_mapand via results evaluationpar_evaluate. Due to Python's parallelism implementation, this is only useful if your mapping function is IO-bound.Note that Lazy Stream does not check for thread safety.fromconcurrent.futuresimportThreadPoolExecutorfromlazystreamimportLazyStreamdefio_bound_function(x):# Do some IO-bound operationreturnxstream=LazyStream.from_iterator(iter(range(10)))stream.par_map(io_bound_function,executor=ThreadPoolExecutor(4)).evaluate()