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.
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