Function chaining in Python
Question: Imagine that there is a function I want to implement by chaining sub-functions. In case you want to apply the chain of functions to multiple arguments, you can create an aggregated function. or more flexible (when there is an arbitrary list of functions): Solution 4: It might be a tad late, but try my solution below. essentially creates a new wrapper function that calls all underlying functions in chain when invoked in runtime.
Function chaining in Python
On Codewars.com I encountered the following task:
Create a function add that adds numbers together when called in succession. So add(1) should return 1 , add(1)(2) should return 1+2 , .
While I’m familiar with the basics of Python, I’ve never encountered a function that is able to be called in such succession, i.e. a function f(x) that can be called as f(x)(y)(z). . Thus far, I’m not even sure how to interpret this notation.
As a mathematician, I’d suspect that f(x)(y) is a function that assigns to every x a function g_ and then returns g_(y) and likewise for f(x)(y)(z) .
Should this interpretation be correct, Python would allow me to dynamically create functions which seems very interesting to me. I’ve searched the web for the past hour, but wasn’t able to find a lead in the right direction. Since I don’t know how this programming concept is called, however, this may not be too surprising.
How do you call this concept and where can I read more about it?
I don’t know whether this is function chaining as much as it’s callable chaining, but, since functions are callables I guess there’s no harm done. Either way, there’s two ways I can think of doing this:
Sub-classing int and defining __call__ :
The first way would be with a custom int subclass that defines __call__ which returns a new instance of itself with the updated value:
class CustomInt(int): def __call__(self, v): return CustomInt(self + v)
Function add can now be defined to return a CustomInt instance, which, as a callable that returns an updated value of itself, can be called in succession:
>>> def add(v): . return CustomInt(v) >>> add(1) 1 >>> add(1)(2) 3 >>> add(1)(2)(3)(44) # and so on.. 50
In addition, as an int subclass, the returned value retains the __repr__ and __str__ behavior of int s. For more complex operations though, you should define other dunders appropriately .
As @Caridorc noted in a comment, add could also be simply written as:
Renaming the class to add instead of CustomInt also works similarly.
Define a closure, requires extra call to yield value:
The only other way I can think of involves a nested function that requires an extra empty argument call in order to return the result. I’m not using nonlocal and opt for attaching attributes to the function objects to make it portable between Pythons:
def add(v): def _inner_adder(val=None): """ if val is None we return _inner_adder.v else we increment and return ourselves """ if val is None: return _inner_adder.v _inner_adder.v += val return _inner_adder _inner_adder.v = v # save value return _inner_adder
This continuously returns itself ( _inner_adder ) which, if a val is supplied, increments it ( _inner_adder += val ) and if not, returns the value as it is. Like I mentioned, it requires an extra () call in order to return the incremented value:
>>> add(1)(2)() 3 >>> add(1)(2)(3)() # and so on.. 6
You can hate me, but here is a one-liner 🙂
Edit: Ok, how this works? The code is identical to answer of @Jim, but everything happens on a single line.
- type can be used to construct new types: type(name, bases, dict) -> a new type . For name we provide empty string, as name is not really needed in this case. For bases (tuple) we provide an (int,) , which is identical to inheriting int . dict are the class attributes, where we attach the __call__ lambda.
- self.__class__(self + v) is identical to return CustomInt(self + v)
- The new type is constructed and returned within the outer lambda.
If you want to define a function to be called multiple times, first you need to return a callable object each time (for example a function) otherwise you have to create your own object by defining a __call__ attribute, in order for it to be callable.
The next point is that you need to preserve all the arguments, which in this case means you might want to use Coroutines or a recursive function. But note that Coroutines are much more optimized/flexible than recursive functions , specially for such tasks.
Here is a sample function using Coroutines, that preserves the latest state of itself. Note that it can’t be called multiple times since the return value is an integer which is not callable, but you might think about turning this into your expected object ;-).
def add(): current = yield while True: value = yield current current = value + current it = add() next(it) print(it.send(10)) print(it.send(2)) print(it.send(4)) 10 12 16
class add(int): def __call__(self, n): return add(self + n)
Function chaining in Python, I don’t know whether this is function chaining as much as it’s callable chaining, but, since functions are callables I guess there’s no harm done. Either way, there’s two ways I can think of doing this: Sub-classing int and defining __call__:. The first way would be with a custom int subclass that defines __call__ which returns a new instance of itself with the updated value: Code sample>>> add(1)functools.partial(
Compute a chain of functions in python
I want to get the result of a chain of computations from an initial value. I’m actually using the following code:
def function_composition(function_list, origin): destination = origin for func in function_list: destination = func(destination) return destination
With each function in function_list having a single argument.
I’d like to know if there is a similar function in python standard library or a better way (example: using lambdas) to do this.
destination = reduce((lambda x, y: y(x)), function_list, origin)
Functional programming — Compute a chain of functions, With each function in function_list having a single argument. I’d like to know if there is a similar function in python standard library or a better way (example: using lambdas) to do this. python functional-programming
Conditional function chaining in Python
Imagine that there is a function g I want to implement by chaining sub-functions. This can be easily done by:
def f1(a): return a+1 def f2(a): return a*2 def f3(a): return a**3 g = lambda x: f1(f2(f3(x)))
However, now consider that, which sub-functions will be chained together, depends on conditions: specifically, user-specified options which are known in advance. One could of course do:
def g(a, cond1, cond2, cond3): res = a if cond1: res = f3(res) if cond2: res = f2(res) if cond3: res = f1(res) return res
However, instead of dynamically checking these static conditions each time the function is called, I assume that it’s better to define the function g based on its constituent functions in advance. Unfortunately, the following gives a RuntimeError: maximum recursion depth exceeded :
g = lambda x: x if cond1: g = lambda x: f3(g(x)) if cond2: g = lambda x: f2(g(x)) if cond3: g = lambda x: f1(g(x))
Is there a good way of doing this conditional chaining in Python? Please note that the functions to be chained can be N, so it’s not an option to separately define all 2^N function combinations (8 in this example).
I found one solution with usage of decorators. Have a look:
def f1(x): return x + 1 def f2(x): return x + 2 def f3(x): return x ** 2 conditions = [True, False, True] functions = [f1, f2, f3] def apply_one(func, function): def wrapped(x): return func(function(x)) return wrapped def apply_conditions_and_functions(conditions, functions): def initial(x): return x function = initial for cond, func in zip(conditions, reversed(functions)): if cond: function = apply_one(func, function) return function g = apply_conditions_and_functions(conditions, functions) print(g(10)) # 101, because f1(f3(10)) = (10 ** 2) + 1 = 101
The conditions are checked only once when defining g function, they are not checked when calling it.
The most structurally similar code I can think of have to be structured in the following way, your f1.. f3 will need to become pseudo decorators, like this:
def f1(a): def wrapper(*args): return a(*args)+1 return wrapper def f2(a): def wrapper(*args): return a(*args)*2 return wrapper def f3(a): def wrapper(*args): return a(*args)**3 return wrapper
And then you can apply these to each functions.
g = lambda x: x if cond1: g = f3(g) if cond2: g = f2(g) if cond3: g = f1(g) g(2)
# Assume cond1..3 are all True 17 # (2**3*2+1)
Python — Itertools.chain(), chain () function It is a function that takes a series of iterables and returns one iterable. It groups all the iterables together and produces a single iterable as output. Its output cannot be used directly and thus explicitly converted into iterables. This function come under the category iterators terminating …
Is there a chain calling method in Python?
Is there a function in Python that would do this:
by typing this (for example):
val = chainCalling(arg,f3,f2,f1)
I just figured, since python is (arguably) a functional language the function I’m looking for will make syntax brighter
Use the reduce() function to chain calls:
from functools import reduce val = reduce(lambda r, f: f(r), (f1, f2, f3), arg)
I used the forward-compatible functools.reduce() function; in Python 3 reduce() is no longer in the built-in namespace.
This can also be made a separate function, of course:
from functools import reduce def chain(*funcs): def chained_call(arg): return reduce(lambda r, f: f(r), funcs, arg) return chained_call
You can use the reduce() functool — as Martijn briantly suggested, or you can write it yourself quite simply:
def chainCalling(arg, *funcs): if len(funcs) > 0: return chainCalling(funcs[0](arg), funcs[1:]) return arg
or, as an alternative not using recursion — so not bound to the call stack limitation, as suggested by Martijn:
def chainCalling(arg, *funcs): result = arg for f in funcs: result = f(result) return result
Obviously, you’ll want to call it that way, to avoid an useless reversal of the arguments:
In case you want to apply the chain of functions to multiple arguments, you can create an aggregated function.
or more flexible (when there is an arbitrary list of functions):
from functools import reduce, partial f3 = lambda x: -x f2 = lambda x: x ** 2 f1 = lambda x: x + 1 function_list = (f1, f2, f3) g = partial(reduce, lambda r, f: f(r), function_list) print(g(3)) # results in -16
It might be a tad late, but try my solution below. chain_func essentially creates a new wrapper function that calls all underlying functions in chain when invoked in runtime.
def chain_func(*funcs): def _chain(*args, **kwargs): cur_args, cur_kwargs = args, kwargs ret = None for f in reversed(funcs): cur_args, cur_kwargs = (f(*cur_args, **cur_kwargs), ), <> ret = cur_args[0] return ret return _chain
Python-chain, Chaining functions is a common functional development pattern that is pretty difficult on Python. Usually, we need to pass some data through a pipeline, process or series of functions in order to get a specific output. Without this lib, you would need to wrap those functions on a class or assign each result on a variable.