Reputation: 23
I've been gradually improving my method of calling functions complete with list of arguments held in dictionary. Where my problem comes in is that the arguments are command line arguments and the functions have varying numbers of arguments. If I call a function that has 2 arguments but the dictionary also has a function with 3, then I will get an "IndexError: list index out of range" re that entry in the dictionary. My code as it stands is
from sys import argv
def func1(num1, num2):
result = int(num1) + int(num2)
print('The sum of {0} and {1} is {2}'.format(num1, num2, result))
def func2(num1, num2, num3):
result = (int(num1) + int(num2) + int(num3)) / 3
print('The average of {0} {1} and {2} is {3}'.format(num1, num2, num3, result))
def func3(string1):
reverse = string1[::-1]
print('{0} reversed is {1}'.format(string1, reverse))
def func4(*args):
pass
def func5(*args):
pass
def main():
option = {
'f1': func1(argv[2], argv[3]),
'f2': func2(argv[2], argv[3], argv[4]),
'f3': func3(argv[2])
}
if len(argv) > 1:
for routine in option:
if routine == argv[1]:
option[routine]()
exit(0)
if __name__ == '__main__':
main()
I'm on a linux system so if I execute
./program.py f1 10 11
it does give the expected result but throws up said IndexError re the dictionary entry mentioning f2. I could turn the dictionary entry re the function and arguments into a string and use eval but that's unsafe obviously but it does do away with the error. So I gather python is interpreting the dictionary entry as a command and throwing the error. From the above code, does anyone have an idea to get past this problem?
Upvotes: 2
Views: 50
Reputation: 17322
when your code it is executed, first it is building your dictionary and there you can see that all the functions are called, as I can assume this is not your expected behavior, you want to call a function base on the line arguments, so you should not call your functions in your dictionary but only after you inspect the second line argument:
option ={
'f1': (func1, slice(2, 4)),
'f2': (func2, slice(2, 5)),
'f3': (func3, slice(2, 3))
}
if len(argv) > 1 and argv[1] in options:
my_function, slice_argv = options[argv[1]][0]
my_function(*argv[slice_argv])
if you are sure that you will give the right number of line arguments for your wanted function you can use:
option ={
'f1': func1,
'f2': func2,
'f3': func3
}
if len(argv) > 1 and argv[1] in options:
my_function[argv[1]](*argv[2:])
Upvotes: 1