1

I have a Python module which has several functions in it and it should call a different function depending on user input. For example, in my code I have something like:

if val == "X":
    return foo.X(self)
elif val == "Y":
    return foo.Y(self)
elif val == "Z":
    return foo.Z(self)
else:
    sys.exit("ERROR: value %s DNE"%(val))

Is there a way to simply call the python function in foo module based on the input directly without multiple if statements?

cs95
  • 379,657
  • 97
  • 704
  • 746
drjrm3
  • 4,474
  • 10
  • 53
  • 91
  • Possible duplicate of [How to access object attribute given string corresponding to name of that attribute](https://stackoverflow.com/questions/2612610/how-to-access-object-attribute-given-string-corresponding-to-name-of-that-attrib) – N Chauhan Jun 02 '19 at 16:28

2 Answers2

2

Use getattr:

class Foo:
    def X(self): return 1
    def Y(self): return 2

foo = Foo()
getattr(foo, 'X')()
1

This works because functions are also attributes of objects. The function can then be called as normal.

But beware, you'll want to handle situations where the passed string does not match any function in Foo. In that case, you can use getattr with an optional third argument:

getattr(foo, 'abcd', lambda : None)()
# None

The lambda is returned when no attribute with that name is found.

cs95
  • 379,657
  • 97
  • 704
  • 746
0

You could use the usual Python way to avoid the switch statement used in other languages: the dictionary. Functions are object, so a function can be a value in a dictionary.

function_dict = {'X': foo.X, 'Y': foo:Y, 'Z': foo.Z}
return function_dict[val](self)

If val is not one of the keys in the dictionary, an error will be raised. If you do not want that particular error, there are several ways to raise another error or avoid errors altogether. For example, you could use the get method of dictionaries to use a default value if the key is not in the dictionary. For example, if you want the method foo.other to be called for any key other than X, Y, Z you could use

function_dict = {'X': foo.X, 'Y': foo:Y, 'Z': foo.Z}
return function_dict.get(val, other)(self)

You could also check before using the dictionary if val is one of the keys, as in

function_dict = {'X': foo.X, 'Y': foo:Y, 'Z': foo.Z}
if val not in function_dict:
    sys.exit("ERROR: value %s DNE"%(val))
return function_dict[val](self)
Rory Daulton
  • 21,934
  • 6
  • 42
  • 50