pythonfunctiondictionaryinspect

Using a dictionary to select function to execute


I am trying to use functional programming to create a dictionary containing a key and a function to execute:

myDict={}
myItems=("P1","P2","P3",...."Pn")
def myMain(key):
    def ExecP1():
        pass
    def ExecP2():
        pass
    def ExecP3():
        pass
        ...
    def ExecPn():
        pass  

Now, I have seen a code used to find the defined functions in a module, and I need to do something like this:

    for myitem in myItems:
        myDict[myitem] = ??? #to dynamically find the corresponding function

So my question is, How do I make a list of all the Exec functions and then assign them to the desired item using the a dictionary? so at the end I will have myDict["P1"]() #this will call ExecP1()

My real problem is that I have tons of those items and I making a library that will handle them so the final user only needs to call myMain("P1")

I think using the inspect module, but I am not so sure how to do it.

My reason to avoid:

def ExecPn():
    pass
myDict["Pn"]=ExecPn

is that I have to protect code as I am using it to provide a scripting feature within my application.


Solution

  • Not proud of it, but:

    def myMain(key):
        def ExecP1():
            pass
        def ExecP2():
            pass
        def ExecP3():
            pass
        def ExecPn():
            pass 
        locals()['Exec' + key]()
    

    I do however recommend that you put those in a module/class whatever, this is truly horrible.


    If you are willing to add a decorator for each function, you can define a decorator which adds each function to a dictionary:

    def myMain(key):
        tasks = {}
        
        def task(task_fn):
            tasks[task_fn.__name__] = task_fn
        
        @task
        def ExecP1():
            print(1)
        @task
        def ExecP2():
            print(2)
        @task
        def ExecP3():
            print(3)
        @task
        def ExecPn():
            print(4)
        
        tasks['Exec' + key]()
    

    Another option is to place all the functions under a class (or in a different module) and use getattr:

    def myMain(key):
        class Tasks:
            def ExecP1():
                print(1)
            def ExecP2():
                print(2)
            def ExecP3():
                print(3)
            def ExecPn():
                print(4)
        
        task = getattr(Tasks, 'Exec' + key)
        task()