patternpythonMinor
Basic math interpreter
Viewed 0 times
interpretermathbasic
Problem
Essentially what I've done here is written an Interpreter that takes in Python math, such as this,
Can I improve anything here? Is it possible for this to be Python3 compatible?
23 ** 374748, and prints out the result. This program relies on the fact that in Python 2.7 input() is "broken". This means it can take in Python math.# Main parser class
class Parser(object):
def __init__(self):
self.PROMPT = "MaTh @ ==> "
self.ERR_MSG = "Error: Invalid math!"
# Parse inputted math
def parse_math(self):
while True:
try:
math = input(self.PROMPT)
print "{}\n".format(math)
except:
print self.ERR_MSG
# Run the program
if __name__ == "__main__":
Parser().parse_math()Can I improve anything here? Is it possible for this to be Python3 compatible?
Solution
For 2.x and 3.x compatibility, I would explicitly use
This makes more sense if you're writing for 2.x first, and is slightly easier than shoehorning
Also for compatibility,
in both.
You could make the constants class attributes:
These are still accessible via
Try giving the user a way to escape the loop. Perhaps:
Note here also
Finally, your code has no documentation. This is simple enough to not really need it, but it's a habit worth getting into. See e.g. PEP-257.
eval(raw_input(...)); you can then use:import sys
if sys.version_info[0] > 2:
raw_input = inputThis makes more sense if you're writing for 2.x first, and is slightly easier than shoehorning
eval onto 3.x's input everywhere you need it (which also makes life more difficult everywhere you don't).Also for compatibility,
print is a function in 3.x. You can import from __future__, or just useprint("{}\n".format(math))in both.
You could make the constants class attributes:
class Parser(object):
PROMPT = "..."
ERR_MSG = "..."
def parse_math(self):
...These are still accessible via
self, so your other code doesn't change. Note that now there are no instance attributes, you don't need __init__. In fact, you could take this further and make parse_math a class method, then you don't need to create an instance to call it. Try giving the user a way to escape the loop. Perhaps:
while True:
math = raw_input(self.PROMPT)
if math.lower() == "done":
break
try:
math = eval(math)
except (NameError, SyntaxError):
print(self.ERR_MSG)
else:
print("{}\n".format(math))Note here also
- Splitting input and evaluation to allow pre-evaluation checking;
- Catching specific errors (see e.g. here); and
- Using the
elseto minimise the code in thetryblock.
Finally, your code has no documentation. This is simple enough to not really need it, but it's a habit worth getting into. See e.g. PEP-257.
Code Snippets
import sys
if sys.version_info[0] > 2:
raw_input = inputprint("{}\n".format(math))class Parser(object):
PROMPT = "..."
ERR_MSG = "..."
def parse_math(self):
...while True:
math = raw_input(self.PROMPT)
if math.lower() == "done":
break
try:
math = eval(math)
except (NameError, SyntaxError):
print(self.ERR_MSG)
else:
print("{}\n".format(math))Context
StackExchange Code Review Q#59646, answer score: 3
Revisions (0)
No revisions yet.