Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to consume/chain functions "Pythonically"?

I have a set of functions f(x), g(x), s(x), t(x).

They are designed to be chained together like this: f(g(s(t(x))))

The functions are designed so they can be chained in any sequence. Another part of my code builds the sequence in a list: [f, g, s, t]

Is there an elegant way to take the list and chain the function calls, getting the output of the last result?

Now obviously I can do it using an outside counter-like variable which tracks the output and a simple for loop increment index, but I was wondering if there is an more Pythonic way to do this?

like image 603
l3utterfly Avatar asked Jun 13 '26 03:06

l3utterfly


2 Answers

Reduce is the perfect answer (though we need to start with the innermost function, thus reversed):

import functools

functions = [f, g, s, t]
y = functools.reduce(lambda a, f: f(a), reversed(functions), x)

EDIT: With constant parameters, as easy as this:

p1, p2 = 5, 42
y = functools.reduce(lambda a, f: f(a, p1, p2), reversed(functions), x)
like image 105
Amadan Avatar answered Jun 15 '26 17:06

Amadan


Martineau and Amadan already posted the "elegant" solution. Now the truly pythonic solution is as stupid, simple an plain boring as it can get:

def chain(arg, *funcs):
    # chain(42, f, g, s) => f(g(s(42)))
    result = arg
    for func in reversed(funcs):
        result = func(result)
    return result

It's clearly not what most people would consider "elegant", but it's perfectly obvious, readable, and is very easy to trace and debug - and that's what matters most wrt/ python's philosophy.

like image 27
bruno desthuilliers Avatar answered Jun 15 '26 17:06

bruno desthuilliers