Utilities and APIs for fluent python coding.
flo
let's you embrace some of the benefits of functional programming in a way that flows more naturally.
Quick motivating example:
Say I have a list:
mylist = ['pretty','cool','items', 'kiddo']
If I want to get only the items containing an 'e' and then index them by their first letter, you could do:
{v[0]: v for v in mylist if 'e' in v}
That's not too bad. But what if you want to apply some mapping first, e. g., Make it all upper case. Then it starts getting ugly:
{v[0]: v for v in (vv.upper() for vv in mylist) if 'E' in v}
Of course, you could do this instead:
{v[0]: v for v in map(str.upper, mylist) if 'E' in v}
Not terrible, but for me, the flow is weird. We start with the end result, then describe the beginning, and then finish with the middle!
What if, instead, the code flowed according to the actual steps of execution:
from flo import from_, for_each, e_, unique_index
(from_(mylist)
.map(e_.upper())
.filter(e_.has('E'))
.collect(unique_index, key=e_[0]))
Or alternatively, a more sql-like syntax:
(from_(mylist)
.apply(e_.upper())
.where(e_.has('E'))
.to(unique_index, key=e_[0]))
Or even more terse
for_each('pretty', 'cool', 'items', 'kiddo') * e_.upper() / e_.has('E') > list
This library was motivated in part by the API for Apache Spark.
Main entry points are:
flo.from_
, which wraps anyIterable
into aflo.It
with methods likemap
(aka,apply
),filter
(aka,where
), andcollect
(aka,to
).- Alternatively,
flo.for_each
, which takes your elements as individual arguments. flo.Lambda
, often abbreviated ase_
, which allows for nearly everything you can do with a Python lambda but with cleaner syntax.flo.DataFrame
andflo.Series
, which provide easier ways to chain commands onpandas
collections.
flo
comes with some nice utilities to complement this api.
-
flo.parallel
provides a common, flo-like API for parallel processing and implementations backed by standard pythonmultiprocessing
andthreading
libraries as well asjoblib
.flo.pmap
andflo.tmap
provide even more convenient entry points for quickly applying a function to an iterable in parallel.
-
flo.try_
, which calls a function and returns anAttempt
containing either a successful result or a failureException
. -
flo.check
for quickly checking pre- and post-conditions.