Home > database >  Python - How to call every function in a list with a single function call
Python - How to call every function in a list with a single function call

Time:10-10

I'm trying to create a dictionary where each value is a list of functions that should get executed when calling the value. Here's some pseudo-code:

functions = {
    "A": (execute() for execute in [func1(param1), func2(param1)]),
    "B": (execute() for execute in [func1(param2), func2(param2)]),
}

But if I try to call this using functions["A"]() an exception is thrown saying "TypeError: 'generator' object is not callable".

How should I approach this problem?

EDIT: Just to clarify, the functions are not generators nor have any return type. They just execute some actions based on the parameter.

CodePudding user response:

So, we have a few issues with your pseudo code!

[func1(param1), func2(param1)] will actually call func1 and func2 and store their return values in the list which is not what you want. Then these return values has to be callable, else the execute() part wont make any sense.

So you need a list of functions to call, and a list of parameters to send into these functions.

So if we instead have a list of tuples to work with we can do something like

to_call = [(len, "hello"), (len, "world!")]

for func, param in to_call:
    func(param)

Will print 5 and 6, so all good.

Then to do this in one function call and return their return values, we can just wrap it in a function

from typing import Sequence, Tuple, Callable, Any # Typing is cool now kids.

def call_list(functions: Sequence[Tuple[Callable, Any]]) -> list[Any]: 
    results = list()
    for func, param in functions:
        results.append(func(param))
    return results

now we can call that function

>>> call_list([(len, "hello"), (len, "world!")])
-> [5, 6]

And with a bit of list comprehension

def call_list(functions: Sequence[Tuple[Callable, Any]]) -> list[Any]: 
    return [func(param) for func, param in functions]

now we can do

functions = {
    "A": [(func1, param1), (func2, param1)],
    "B": [(func1, param2), (func2, param2)],
}

call_list(functions["A"])

CodePudding user response:

I don't think you want to create a generator at all.

You can try something like this:

# A function that returns a different function that calls each function in functions in sequence
def call_functions(functions, param):
    # Define a inner function
    def _inner():
        # For each function
        for function in functions:
            # Call it
            function(param)
    # return the inner function
    return _inner

# Define a dict mapping strings to functions.
to_call = {
    "A": call_functions([func1, func2], param1),
    "B": call_functions([func1, func2], param2)
}

to_call["A"]()
# This will do basically the same as:
# > func1(param1)
# > func2(param1)

CodePudding user response:

As has been pointed out, the use of a generator is flawed.

Also, in the original code, both func1 and func2 would have to return references to other functions in order for that to work

It's more likely that what you need is something like this:

def func1(p):
    pass

def func2(p):
    pass

functions = {
    "A": [func1, func2]
}

param1 = 0

for func in functions['A']:
    func(param1)
  • Related