1

I'm trying to execute a list of functions with the output of some functions being used as inputs to other ones.

A simplified example of what I'm trying to do:

def a():
    return 25

def b():
    return 50

def c(x, y):
    return x+y

Normally, I'd do: print c(a(), b())

But if I have a list of functions: l = [a,b,c]

How can I iterate over this list and get the right arguments passed into method c?

Thanks.

6
  • 1
    l[2](l[0](), l[1]()) Commented Jul 16, 2014 at 0:29
  • are the functions in the list guaranteed to be in that order? Commented Jul 16, 2014 at 0:29
  • Your probably gonna need to include additional examples as well as a bit more information about how you intend to use it. Commented Jul 16, 2014 at 0:34
  • pass the funcs as keywords args def c(x=a(), y=b()): Commented Jul 16, 2014 at 0:40
  • Do the lists of functions change size? Is it always the last function that gets called with the results of the functions leading up to it? Commented Jul 16, 2014 at 0:43

3 Answers 3

2

My previous answer was not generic enough, so here's another bash at it. This uses inspect.getargspec() to determine the arity of each function prior to calling it. With that knowledge the required number of arguments can be sliced out of a "results list" which contains the results of all previous function calls.

There are some limitations:

  • inspect.getargspec() doesn't work for built-in functions, only user defined ones.
  • varargs and keyword args are ignored because this results in possibly infinite arguments which just complicates things.

Code:

import inspect

def a():
    return 25

def b():
    return 50

def c(x, y):
    return x + y

def d(x, y, z):
    return x + y + z

def e(x=100):
    return x * x

def f():
    pass


def execute_function_list(funcs):
    results = []
    for i, fn in enumerate(funcs):
        args_required = len(inspect.getargspec(fn).args)
        if args_required > 0:
            args = results[i-args_required:i]
        else:
            args = ()
        print("calling function %r with args %r" % (fn, args))
        results.append(fn(*args))
        print("after function returned results = %r" % results)
    return results[-1] if len(results) else None

if __name__ == '__main__':
    funcs = [e, a, b, c, d, e]
    print("final result is %r" % execute_function_list(funcs))
Sign up to request clarification or add additional context in comments.

1 Comment

This is the closest to what I'm trying to do and put me on the right track. Thank you.
1

Assuming that the last function in the list is to be called with the results of all of the preceding functions in the list:

def c(*args):
    "Return the sum of all function arguments"
    return sum(args)

>>> l = [a, b, a, b, b, b, c]
>>> args=(f() for f in l[:-1])
>>> args
<generator object <genexpr> at 0x7fd441aabe60>
>>> l[-1](*args)
250

or in one line,

>>> l[-1](*(f() for f in l[:-1]))
250

2 Comments

Thank you. While this works for the example in my question, what I have is a more generic list of functions that I need to execute in order. Some of these functions accept arguments whose values are returned by one or more previous functions. So I need to keep track of the value returned by the first method, for instance, and pass it into the 2nd and 3rd one, the output of method 3 goes into method 4 etc.
In that case, what would be done with the output of the 2nd method? Would it not have an output (returns None) in that example? If the latter is the case, then it seems like a recursive helper method would do the job.
0

You can try the built-in function apply:

apply( l[-1], [ func() for func in l[:-1] ] )

1 Comment

This doesn't work, besides, apply has been deprecated since 2.3. This will do it though: apply( l[-1], [f() for f in l[:-1]] )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.