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)