Search code examples
pythonvariablessubroutine

Can you use a variable to call a function


I have four subroutines to multiply, divide, add and subtract 2 numbers which I will ask the user for.

My unfinished code is:

def multiply(a, b):
    print(f"{a} x {b} = {a*b}")
    
def divide(a, b):
    print(f"{a} ÷ {b} = {a*b}")

num1 = int(input("What is the first number?\n"))
num2 = int(input("What is the second number?\n"))
calculation = input("What calculation would you like to perform? [multiply, divide]\n")

calculation(num1, num2)

but it gives TypeError: 'str' object is not callable

Is it necessary to use if statements like:

if calculation == 'multiply':
     multiply()
elif calculation == 'divide':
     divide()

for all four subroutines or can I use the variable calculation to substitute for the function name.


Solution

  • Use a dictionary to hold your functions

    funcs = {'multiply': multiply, 'divide': divide}
    

    and then access funcs[calculation].

    ... or if you have a DRY fetish:

    funcs = {f.__name__: f for f in [multiply, divide]}
    

    Demo:

    >>> funcs['multiply'](3, 4)
    3 x 4 = 12
    

    You could also access the globals() dict

    >>> globals()['multiply'](3, 4)
    3 x 4 = 12
    

    but this is not such a good idea because the function to call comes from user input and who knows what weird callables are in globals().


    Bonus: safeguarding against bad input

    from functools import partial
    def notfound(fname, *_, **__):
        print(f'function {fname!r} not found')
    

    Usage:

    >>> calculation = 'multiply'
    >>> funcs.get(calculation, partial(notfound, calculation))(3, 4)
    3 x 4 = 12
    >>> calculation = 'none'
    >>> funcs.get(calculation, partial(notfound, calculation))(3, 4)
    function 'none' not found