-1

I'm new to Python and using Anaconda (editor: Spyder) to write some simple functions. I've created a collection of 20 functions and saved them in separate .py files (file names are the same as function names).

For example

def func1(X)
    Y=...
    return Y

I have another function that takes as input a function name as string (one of those 20 functions), calls it, does some calculations and return the output.

def Main(String,X)
    Z=...
    W=String(Z)
    V=...
    return V

How can I choose the function based on string input?

More details: The Main function calculates the Sobol Indices of a given function. I write the Main function. My colleagues write their own functions (each might be more than 500 lines of codes) and just want to use Main to get the Sobol indices. I will give Main to other people so I do NOT know what Main will get as a function in the future. I also do not want the user of Main to go through the trouble of making a dictionary.

R.b
  • 15
  • 5
  • Make a function dispatch dictionary, store the strings as keys then the functions as values. Call by looking up the functions and passing the parameter to that dictionary lookup result. – shuttle87 Aug 14 '15 at 14:12
  • possible duplicate of [Calling a function of a module from a string with the function's name in Python](http://stackoverflow.com/questions/3061/calling-a-function-of-a-module-from-a-string-with-the-functions-name-in-python) – akalikin Aug 14 '15 at 14:15
  • Why does it take the name of the function as a string? Functions are first-class objects; just pass a reference to the function itself. – chepner Aug 14 '15 at 14:51
  • Also, is there a reason you don't just put all 20 functions in a single module? – chepner Aug 14 '15 at 14:52
  • The Main function calculates the Sobol Indices of a given function. I write the Main function. My colleagues write their own functions (each might be more than 500 lines of codes) and just want to use Main to get the Sobol indices. I will give Main to other people so I do NOT know what I will get as a function in the future. I also do not want them to go through the trouble of making a dictionary. – R.b Aug 14 '15 at 15:11

2 Answers2

0

Functions are objects in Python. This means you can store them in dictionaries. One approach is to dispatch the function calls by storing the names you wish to call as keys and the functions as values.

So for example:

import func1, func2
operation_dispatcher = {
    "func1": getattr(func1, "func1"),
    "func2": getattr(func2, "func2"),
}

def something_calling_funcs(func_name, param):
    """Calls func_name with param"""
    func_to_call = operation_dispatcher.get(func_name, None)
    if func_to_call:
        func_to_call(param)

Now it might be possible to generate the dispatch table more automatically with something like __import__ but there might be a better design in this case (perhaps consider reorganizing your imports).

EDIT took me a minute to fully test this because I had to set up a few files, you can potentially do something like this if you have a lot of names to import and don't want to have to specify each one manually in the dictionary:

import importlib
func_names = ["func1", "func2"]
operation_dispatch = {
    name : getattr(importlib.import_module(name), name)
    for name in func_names}

#usage
result = operation_dispatch[function_name](param)

Note that this assumes that the function names and module names are the same. This uses importlib to import the module names from the strings provided in func_names here.

shuttle87
  • 15,466
  • 11
  • 77
  • 106
  • the edit part solved my problem. thanks. Would u please look at my comment in the above answer and see if my question is well posed or is duplicate? – R.b Aug 14 '15 at 15:14
  • You should edit your question to try to explain the use case more, the comment contains important information that really should be in the question. The real question really appears to be about creating a function dispatch table automatically that pull out the relevant functions from the files. The simpler problem of just calling a function by a related string is definitely a duplicate. – shuttle87 Aug 14 '15 at 15:24
0

You'll just want to have a dictionary of functions, like this:

call = {
          "func1": func1,
          "functionOne": func1,
          "func2": func2,
       }

Note that you can have multiple keys for the same function if necessary and the name doesn't need to match the function exactly, as long as the user enters the right key.

Then you can call this function like this:

def Main(String,X)
    Z=...
    W=call[String](Z)
    V=...
    return V

Though I recommend catching an error when the user fails to enter a valid key.

def Main(String,X)
    Z=...
    try:
        W=call[String](Z)
    except KeyError:
        raise(NameError, String + " is not a valid function key")
    V=...
    return V
SuperBiasedMan
  • 9,814
  • 10
  • 45
  • 73
  • much easier to do getattr(module_name, String) – akalikin Aug 14 '15 at 14:29
  • 2
    @akalikin I think they're pretty equally complex, since they're just two different ways of accessing the function. The small downside to `getattr` is that it only works because the OP is importing everything. If they refactored code to put them all in one file, that solution no longer works. – SuperBiasedMan Aug 14 '15 at 14:32
  • 1
    f = getattr(sys.modules[__name__], String) in that case. Still saves the trouble of adding functions to a dictionary – akalikin Aug 14 '15 at 14:37