mottosan
mottosan

Reputation: 486

Invoking a list of methods with correct arguments in Python

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.

Upvotes: 1

Views: 69

Answers (3)

mhawke
mhawke

Reputation: 87134

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))

Upvotes: 2

zhujs
zhujs

Reputation: 553

You can try the built-in function apply:

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

Upvotes: 0

mhawke
mhawke

Reputation: 87134

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

Upvotes: 1

Related Questions