Reputation: 43
How can I improve (reduce the writing) for this if-else block to run a method based on an option entered? I've tried looking at SO and various other areas for solutions but didn't find something fit my problem.
def funcA(arg1, arg2):
...
def funcB(arg1):
...
def funcC():
...
def funcD():
...
def funcE():
...
if option == 1:
funcA(arg1, arg2)
elif option == 2:
funcB(arg1)
elif option == 3:
funcC()
elif option == 4:
funcD()
elif option == 5:
funcE()
else:
pass
Apologies if the code is not clear.
Upvotes: 1
Views: 532
Reputation: 42139
You can use a helper function fo imitate a switch/case statement and avoid the ugly repetitions (and corresponding maintenance hassles):
def switch(value): yield lambda *match: value in match
example usage:
for case in switch(option):
if case(1): funcA(arg1, arg2)
elif case(2): funcB(arg1)
elif case(3): funcC()
elif case(4): funcD()
elif case(5): funcE()
Upvotes: 0
Reputation: 7363
You could use a dictionary as a dispatch-table, and namedtuples
to store a function & argument pairing.
from collections import namedtuple
def funcA(arg1, arg2):
print(f'I am funcA and you gave me {arg1} and {arg2}')
def funcB(arg):
print(f'I am funcB and you gave me {arg}')
def funcC():
print(f'I am funcC')
def funcD():
print(f'I am funcD')
def funcE():
print(f'I am funcE')
OptionPairing = namedtuple('OptionPairing', ['f', 'args'])
dispatch = {
1: OptionPairing(funcA, [True, False]),
2: OptionPairing(funcB, [True]),
3: OptionPairing(funcC, []),
4: OptionPairing(funcD, []),
5: OptionPairing(funcE, [])
}
for i in range(1, 6):
choice = dispatch[i]
x = choice.f(*choice.args)
Running this, then, gives the following results:
I am funcA and you gave me True and False
I am funcB and you gave me True
I am funcC
I am funcC
I am funcE
If you want to specify yourself what arguments to pass to your function, simply this will suffice:
dispatch = {
1: funcA,
2: funcB,
3: funcC,
4: funcD,
5: funcE,
}
Then call your function like so:
dispatch[option](args)
Making sure to pass the arguments args
, as a list, since the number of arguments is variadic.
Upvotes: 2
Reputation: 6298
You can use a dictionary of the functions and their args :
actions = {
1: [ func1 , [arg1,arg2] ]
2: [ func2 , [arg1] ]
3: [ func3 , []]
4: [ func4 , []]
5: [ func5 , []]
}
def doAction( actions , option ):
if option in actions:
func, args = actions[option]
func(*args)
Upvotes: 0
Reputation: 5702
It is common in python to do a switch-like struct with a dictionary as you said. However in your case the if/else looks ok I think since the following is a bit obfuscated:
option = 2
def funcA(arg1, arg2):
print("A")
def funcB(arg1):
print("B")
def funcC():
print("C")
def funcD():
print("D")
def funcE():
print("E")
func, args = {
1: (funcA, ("arg1", "arg2")),
2: (funcB, ("arg1",)),
3: (funcC, ()),
4: (funcD, ()),
5: (funcE, ()),
}.get(option, (None, (),))
if func:
func(*args)
It really depends on how many functions and args you have but I would suggest for a few functions to stick to if/else
Upvotes: 0
Reputation: 280
You could have a dictionary approach?
funcs = {
1: funcA,
2: funcB,
...
}
func = funcs.get(option)
if func is None:
return
print(f"Running func: {func.__name__}")
func(*args, **kwargs)
Upvotes: 1