I'm making a program which has a main menu that asks the user to input an option and store it in integer option1
, which is looked up in dictionary options
. The corresponding function is then run. The following code works if the functions have no parameters:
options = {0 : FunctionZero, # Assign functions to the dictionary
1 : FunctionOne,
2 : FunctionTwo,
3 : FunctionThree}
options[option1]() # Call the function
If the functions have parameters the above code doesn't work as the ()
part assumes the functions have no parameters, but I tried the following, which stores the functions' names and parameters in tuples within the dictionary:
options = {0 : (FunctionZero,""), # FunctionsZero, FunctionOne
1 : (FunctionOne,""), # and FunctionTwo have no parameters
2 : (FunctionTwo,""),
3 : (FunctionThree,True)} # FunctionThree has one parameter
if options[option1][1] == "": # Call the function
options[option1][0]()
else:
options[option1][0](options[option1][1])
This code seems to work fine, but I was wondering if there's a better way to do this, especially if the functions require several parameters? In other languages like C# I'd probably use a switch or case statement (which is not in Python) and I'm avoiding using if...elif
statements for this.
Passing Dictionary as kwargs “ kwargs ” stands for keyword arguments. It is used for passing advanced data objects like dictionaries to a function because in such functions one doesn't have a clue about the number of arguments, hence data passed is be dealt properly by adding “**” to the passing type.
Dictionaries in Python Almost any type of value can be used as a dictionary key in Python. You can even use built-in objects like types and functions.
Inside the function, the kwargs argument is a dictionary that contains all keyword arguments as its name-value pairs. Precede double stars ( ** ) to a dictionary argument to pass it to **kwargs parameter. Always place the **kwargs parameter at the end of the parameter list, or you'll get an error.
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
Sure. In Python, functions can take positional or keyword arguments. For most functions, arguments can be passed in either way, but that’s not necessarily the case for all functions, so we do need to keep them separate. Positional arguments are in an iterable (often list or tuple), and keyword arguments are in a dictionary from strings to values.
We could then represent each function as a tuple of function, positional arguments, and keyword arguments:
options = {
0: (function_zero, [], {}),
1: (function_one, [], {}),
2: (function_two, [], {}),
3: (function_three, [True], {}),
4: (function_four, [], {'kwarg': True}), # takes a keyword argument
}
Then you could call them like this:
func, args, kwargs = options[option1]
func(*args, **kwargs)
But if you’re always going to just pass in a constant, there’s a better way: just create little no-argument wrappers for each function that call the function how you want it to be called:
options = {
0: function_zero,
1: function_one,
2: function_two,
3: lambda: function_three(True),
4: lambda: function_four(kwarg=True),
}
Then use your first method:
options[option1]()
As detailed in jonrsharpe’s answer, you can also use functools.partial
rather than a lambda
. As he notes, this has the advantage of being able to append some of your own arguments:
options[option1]('hello') # adds 'hello' to previously-specified arguments
If you don’t need this functionality, though, a zero-parameter lambda
will serve you just fine.
To add to icktoofay's answer, if you want to pass an argument to the lambda just do the following:
def printDouble( number ):
print number * 2
options = {
1: lambda num: printDouble(num)
}
options[1](4) #this prints 8
By adding the parameter for lambda before the ":" you state that the lambda receives a parameter and it is used then in the function it calls.
Also if you don't want to use lambdas you can use the usual way
def printDouble( num ):
print num * 2
def printHalf( num ):
print half / 2
functionDictionary = {
'Double': printDouble,
'Half' : printHalf
}
functionDictionary['Double'](2) #This prints 4
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With