Using a Dictionary to Select Function to Execute

Using a dictionary to select function to execute

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

Calling a function in program from a dictionary

As a very simplified demo of what it you are attempting to do, look at the following:

def northOfHouse():
print "north"
action = raw_input()
myDict[action]()
def westOfHouse():
print "west"
action = raw_input()
myDict[action]()

myDict = {
"WEST": westOfHouse,
"NORTH": northOfHouse
}

action = raw_input()
myDict[action]()

First I've defined 2 functions (northOfHouse and westOfHouse). Each of this functions will simply print there location and ask for a new input. They will then attempt to call the function for the given input in the dictonary.

Next I define the dictionary, in my case using the keys "WEST" and "NORTH" to reference the correct functions(note that I'm not calling the functions). These can then be called using the appropriate myDict["WEST"]() or myDict["NORTH"]() as you would expect.

Using this it's possible to enter "NORTH" and "WEST" and see the appropriate function being called, this can obviously be expanded to what you want to do (with the inclusion of appropriate input validation and performing these instructions on a loop basis rather than recursively of course as with the code provided, recursion depth errors will haunt you after too long).

Another thing I'd recommend is to return a dictionary from each function, that way the current location determines where you can move to next:

def northOfHouse():
print "You're in the NORTH of the house\nYou can go 'WEST'"
myDict = {
"WEST": westOfHouse
}
return myDict

def westOfHouse():
print "You're in the WEST of the house\nYou can go 'NORTH'"
myDict = {
"NORTH": northOfHouse
}
return myDict

currentMoves = northOfHouse()
while 1:
action = raw_input()
if(action in currentMoves):
currentMoves = currentMoves[action]()
else:
print "Invalid Input"

Try Here on repl.it

Using dictionary to select function to run

You are calling the functions while declaring the dict. You also forgot to call you function at the end with ().

Try this:

def set_race(self, race):

race_list = {
"Dragonborn": self.character_race.select_dragonborn,
"Dwarf": self.character_race.select_dwarf,
"Elf": self.character_race.select_elf,
"Gnome": self.character_race.select_gnome,
"Half-Elf": self.character_race.select_halfelf,
"Halfling": self.character_race.select_halfling,
"Half-Orc": self.character_race.select_halforc,
"Human": self.character_race.select_human,
"Tiefling": self.character_race.select_tiefling
}

race_list[race]()

Call a function when it is stored as dictionary value

Simply call dic['c']() to run your function. Hope I helped!

Python dict to select function runs all of them

You're not storing your execute function in your options dict. You're storing the result of calling that function. And since it's the same function either way with different parameters being passed in, you don't actually need the function to be the values in your dict. You need the parameters. Change your last four lines to:

options = {
"BACKUP": [self.jobtype, self.src, self.dst],
"RESTORE": [self.jobtype, self.dst, self.src],
}
execute(*options[jobtype])

Calling functions with parameters using a dictionary in Python

I would do this using functools.partial to specify the arguments when the dictionary is created:

from functools import partial

options = {0: FunctionZero,
1: FunctionOne,
2: FunctionTwo,
3: partial(FunctionThree, True)}

Note that this also allows additional parameters to be passed when the function is called (as long as all the functions in the dictionary have the same parameters missing after partial has been called):

def test(one, two, three=None, four=None):
...

def test2(one, two, three=None):
...

options = {1: partial(test, 1, three=3, four=4),
2: partial(test2, 1, three=3)}

...

options[choice](2) # pass the 'two' argument both functions still require

Dictionary value as function to be called when key is accessed, without using ()

Another possible solution, is to create a custom dictionary object that implements this behavior:

>>> class CallableDict(dict):
... def __getitem__(self, key):
... val = super().__getitem__(key)
... if callable(val):
... return val()
... return val
...
>>>
>>> d = CallableDict({1: "A", 2: "B", 3: lambda: print('run')})
>>> d[1]
'A'
>>> d[3]
run

A perhaps more idiomatic solution would be to use try/except:

def __getitem__(self, key):
val = super().__getitem__(key)
try:
return val()
except TypeError:
return val

Note however the method above is really for completness. I would not reccomend using it. As pointed out in the comments, it would mask TypeError's raised by the function. You could test the exact content of TypeError, but at that point, you'd be better of using the LBYL style.



Related Topics



Leave a reply



Submit