Taking user input for two variables, an arithmetic operator and computing the results is very basic. This article projects a fresh look at extending the simple calculator by evaluating complex arithmetic expressions input by the user while also providing a mechanism to include the last computed value in a follow-up expression. All of these in only a few lines of code, by exploiting the Python's eval function.
Disclaimer: All the source code provided in this article was tested only on Python version 3.12. If the code is being tested on a different Python version, it may or may not work as intended.
Python's eval function is used to evaluate valid Python statement(s). To extend the basic calculator, the user input arithmetic expression can be evaluated using the eval function, store and display the results. To write such an evaluator, the following are added,
- a simple command line interpreter in a loop
- a small command parser
- a set of commands apart from the expressions
- a parser for validating the expressions
- an evaluator to store and display the results of the expression
Let's start with the command line interpreter, the function of such an interpreter is to take input from the user an arithmetic expression or a command, evaluate and display back the results. While starting the program, a small help will be shown to the user, and it drops to a command line interpreter, waiting for the user to input a command or expression. Once the user types in the input, the interpreter then offloads the parsing and execution to a different method. The start method and the command loop are coded as follows,
def expr_loop(): print("Execute arithmetic expressions") print("Hint: Use '$' to substitute the last result") print("Examples: 3 + 4 will yield 7, followed by $ + 8 will yield 15") print("Type 'q' or 'quit' to exit the interpreter") while True: cmd = input("> ") handle_cmd(cmd) expr_loop()
The command parser is fairly simple, there only command it needs to parse it whether to quit the command line interpreter. It also takes care of empty command (no-op). After validating the input expression, it will hand off the expression to the evaluator for the results. The simple command parser looks like,
def handle_cmd(cmd): if cmd is None or cmd == "": return cmd = cmd.strip() if cmd.lower() in ["q", "quit"]: exit(0) if not is_valid_expr(cmd): print("Invalid arithmetic expression") return evaluate(cmd)
To avoid executing Python statements input by the user, the expression needs to be validated to only have a subset of characters and numbers present in it. The list includes the following,
- all digits 0 to 9
- white spaces
- arithmetic operators (including modulo)
- open and close brackets (for forcing precedence)
- dollar ($) sign (used as a substitute for the result from the last operation)
def is_valid_expr(expr): for c in expr: if not (c.isnumeric() or c.isspace() or c in ['.', '+', '-', '%', '*', '/', '$', ')', '(']): return False return True
Finally, the evaluator method which does the computation of the expression. The first step is to substitute for the dollar ($) symbol with the last computation result. A global variable is used which hold the value from the most recent computation. It gets overwritten with every new successful evaluation of a command. While using the eval function, a set of exceptions could be thrown. These exceptions are caught and handled accordingly as shown.
g_last_result = 0 def evaluate(expr): try: global g_last_result expr = expr.replace('$', "g_last_result") g_last_result = eval(expr) print(g_last_result) except SyntaxError: print("Invalid syntax for the arithmetic expression") except NameError: print("Invalid arithmetic expression")
The below is the invocation result of a session which covers all the positive and negative test cases.
$> python expr.py Execute arithmetic expressions Hint: Use '$' to substitute the last result Examples: 3 + 4 will yield 7, followed by $ + 8 will yield 15 Type 'q' or 'quit' to exit the interpreter > > 3 + 9 + 12 24 > $ + 6 30 > $ * 5 150 > $ 150 > $1 Invalid arithmetic expression > (1+) Invalid syntax for the arithmetic expression > print() Invalid arithmetic expression > $_1 Invalid arithmetic expression > (2.5 * 4.2) + (8.1 * 7.9) 74.49000000000001 > $ + 2 76.49000000000001 > q
Thanks for reading, please leave your suggestions, comments or queries in the comment section.
Comments
Post a Comment