Skip to content
Advertisement

Executing functions through dictionaries

My script executes depending on user’s input, like this:

while option != e
   option = input("What to do? ")
   if option == 'l':
     sh.send('lock')
   elif 's1':
     sh.send('start','program1')
   elif 's2':
     sh.send('start','program2)

The problem is that I can have over 15 different choices, so I would like to make it cleaner using dicts, but I can’t get it to work. This is what I did. In the class init for sh:

self.operations = {"l": lambda: self.send('lock'),
                   "s1": lambda x: self.send('start', x),
                   "s2": lambda x: self.send('start', x)}

And so on. Further down in the class:

def user_input(self, key):
    return self.operations[key]

And finally the input part of my script is much cleaner

while option != e
   option = input("What to do? ")
   try:
      sh.user_input(option)()
   except KeyError:
      print('Invalid Operation')
   

This is as far as I got, and while it works for options without parameters, how can I make it work also for commands that need a second parameter?

Advertisement

Answer

To create a dispatcher, you need to combine the function/dictionary/lambdas like this:

def operations(self, key, x):
    return {
    "l": lambda: self.send('lock'),
    "s1": lambda: self.send('start', x),
    "s2": lambda: self.send('start', x)
    }.get(key, lambda: None)

which you can call with self.operations("s1", 2). To evaluate it and get the result, you may need to do self.operations("s1", 2)().

Or, you need a value evaluated and returned, you can also write the function with the () at the end:

def operations(self, key, x):
    return {
    "l": lambda: self.send('lock'),
    "s1": lambda: self.send('start', x),
    "s2": lambda: self.send('start', x)
    }.get(key, lambda: None)()

lambda: None, is the default for what happens if no valid key is passed. It needs to be a lambda to avoid getting: TypeError: 'NoneType' object is not callable (because None itself isn’t), but you can change this to something that makes sense for your purpose.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement