How to compose a nested function g=fn(...(f3(f2(f1()))...) from a list of functions [f1, f2, f3,...fn]
One way using functools.reduce
:
from functools import reduce
f1 = lambda x: x+1
f2 = lambda x: x*2
f3 = lambda x: x+3
funcs = [f1, f2, f3]
g = reduce(lambda f, g: lambda x: g(f(x)), funcs)
Output:
g(1)==7 # ((1+1) * 2) + 3
g(2)==9 # ((2+1) * 2) + 3
Insight:
functools.reduce
will chain its second argument (funcs
here) according to its first argument (lambda
here).
That being said, it will start chaining f1
and f2
as f_21(x) = f2(f1(x))
, then f3
and f_21
as f3(f_21(x))
which becomes g(x)
.
One problem with the reduce
-baed approach is that you introduce O(n) additional function calls. An alternative is to define a single function that remembers the functions to compose; when called, it simply calls each function in sequence on the given argument.
def compose(*args):
"""compose(f1, f2, ..., fn) == lambda x: fn(...(f2(f1(x))...)"""
def _(x):
result = x
for f in args:
result = f(result)
return result
return _
You can implement it yourself, but you could also try a module named compose
which implements this, written by @mtraceur. It takes care to handle various details, such as correct function signature forwarding.
pip install compose
from compose import compose
def doubled(x):
return 2*x
octupled = compose(doubled, doubled, doubled)
print(octupled(1))
# 8