Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a chain calling method in Python?

Tags:

python

Is there a function in Python that would do this:

val = f3(f2(f1(arg)))

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

like image 379
Shai Ben-Dor Avatar asked Jan 05 '16 14:01

Shai Ben-Dor


People also ask

Can you method chain in Python?

Some Python libraries, such as pandas, NumPy, and Pillow (PIL), are designed so that methods can be chained together and processed in order (= method chaining). Method chaining is not a special syntax, as it is just repeating the process of calling a method directly from the return value.

What does __ call __ do in Python?

The __call__ method enables Python programmers to write classes where the instances behave like functions and can be called like a function. When the instance is called as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x.

What is chaining in pandas?

Pandas chaining is an alternative to variable assignment when transforming data. Those in favor of chaining argue that the code is easier to read because it lays out the execution of the transformation like a recipe.


2 Answers

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
like image 102
Martijn Pieters Avatar answered Sep 28 '22 07:09

Martijn Pieters


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:

chainCalling(arg, f1, f2, f3)
like image 33
zmo Avatar answered Sep 28 '22 06:09

zmo