import functools
def compose(*funcs):
"""Functional composition [f, g, h] will be h(g(f(x))) """
def compose_two(f, g):
def c(x):
return f(g(x))
return c
return functools.reduce(compose_two, reversed(funcs))
def adder(a: int, b: int) -> int:
return a + b
def multiply(n: int):
def wrapper(m: int) -> int:
return m * n
return wrapper
add_one = functools.partial(adder, 1)
add_two = functools.partial(adder, 2)
f = compose(add_one, multiply(3), add_two)
assert f(7) == 26
fp = compose(f, print)
fp(7)
This is a 4 Part Series that explores functional centric design style and patterns in Python.
Part 1 (notebook) starts with different mechanisms of how to define functions in Python and quickly moves to using closures and functools.partial
. We then move on to adding functools.reduce
and composition with compose to our toolbox. Finally, we conclude with adding lazy map
and filter
to our toolbox and create a data pipeline that takes a stream of records to compute common statics using a max heap as the reducer.
In Part 2 (notebook), we explore building a REST client using functional-centric design style. Using an iterative approach, we build up a REST client using small functions leveraging clsoures and passing functions as first class citizens to methods. To conclude, we wrap the API and expose the REST client via a simple Python class.
Part 3 (notebook) follows similarly to spirit to Part 2. We build a commandline interface leveraging argparse
from the Python standard library. Sometimes libraries such as argparse can have rough edges or friction points in the API that introduce duplication or design issues. Part 3 focuses on iterative building up an expressive commandline interface to a subparser commandline tool using closures and functions to smooth out the rough edges of argparse.
. There's also examples of using a Strategy-ish pattern with type annotated functions to enable configuring logging as well as custom error handling.
Part 4 (notebook) concludes with some gotchas with regards to scope in closures, a brief example of decorators and a few suggestions for leveraging function-centric designs in your APIs or applications.
If you're a OO wizard, a Data Scientist/Analysist, or a backend dev, this series can be useful to expand your skillset and provide you with a new design approach to building APIs or applications.