Using a dictionary to select function to execute

Simplify, simplify, simplify:

def p1(args):
    whatever

def p2(more args):
    whatever

myDict = {
    "P1": p1,
    "P2": p2,
    ...
    "Pn": pn
}

def myMain(name):
    myDict[name]()

That's all you need.


You might consider the use of dict.get with a callable default if name refers to an invalid function—

def myMain(name):
    myDict.get(name, lambda: 'Invalid')()

(Picked this neat trick up from Martijn Pieters)


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

Simplify, simplify, simplify + DRY:

tasks = {}
task = lambda f: tasks.setdefault(f.__name__, f)

@task
def p1():
    whatever

@task
def p2():
    whatever

def my_main(key):
    tasks[key]()