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') > listThis library was motivated in part by the API for Apache Spark.
Main entry points are:
flo.from_, which wraps anyIterableinto aflo.Itwith 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.DataFrameandflo.Series, which provide easier ways to chain commands onpandascollections.
flo comes with some nice utilities to complement this api.
-
flo.parallelprovides a common, flo-like API for parallel processing and implementations backed by standard pythonmultiprocessingandthreadinglibraries as well asjoblib.flo.pmapandflo.tmapprovide even more convenient entry points for quickly applying a function to an iterable in parallel.
-
flo.try_, which calls a function and returns anAttemptcontaining either a successful result or a failureException. -
flo.checkfor quickly checking pre- and post-conditions.