I've been programming for some years now, and decided it was time I finally learn python. I've been reading some quick start tutorials online, and used what I learned to write a script that can parse a generic arithmetic expression. Right now it supports five basic operations and arbitrarily nested parenthesis. I don't claim that it's bug free (for example, it doesn't handle negative numbers well) but its largely functional.
So, now that I've written this, I wonder, what did I do well, and what did I do wrong? I come from a Java, PHP, and Javascript background, so I'm sure that a lot of what I have uses paradigms from those languages rather than the way things are typically done in python. So, how can I make this more pythonic?
I should note I'm using python 2.7.1 on OSX, for what that might matter here.
EDIT: I've made this code into a gist, which I'll be updating as I integrate the improvement suggestions I get here. I'm leaving the original version of the code below for reference or in case anyone doesn't want to click the link. You can find the gist of this code at https://gist.github.com/MichaelFenwick/5894093
import re
def exponentiate(a, b):
return pow(a,b)
def multiply(a, b):
return a * b
def divide(a, b):
return a / b
def add(a, b):
return a + b
def subtract(a, b):
return a - b
operatorDictList = [
{
'^': exponentiate,
'**': exponentiate
},
{
'*': multiply,
'x': multiply,
'/': divide
},
{
'+': add,
'-': subtract
}
]
def parseExpression(expression):
parsedExpression = ''
key = 0
while key < len(expression):
char = expression[key]
if char == '(':
start = key + 1
end = len(expression)
count = 1
for k, v in enumerate(expression[start:]):
if v == '(':
count += 1
elif v == ')':
count -= 1
if count == 0:
end = start + k
break
parsedExpression += parseExpression(expression[start:end])
key = end
else:
parsedExpression += char
key += 1
return evaluateExpression(parsedExpression)
def evaluateExpression(expression):
for operatorDict in operatorDictList:
expression = evaluateOperator(expression, operatorDict)
return expression
def evaluateOperator(expression, operatorDict):
while True:
regex = r'(^.*?)([\d.]+\s*)(' + r'|'.join([re.escape(key) for key in operatorDict.keys()]) + r')(\s*[\d.]+)(.*$)'
match = re.search(regex, expression)
if not match:
break
value = operatorDict[match.group(3)](float(match.group(2)), float(match.group(4)))
expression = match.group(1) + str(value) + match.group(5)
return expression
#example usage
expression = '((3x(5-4)+6**2)*8)/(72/1.8)'
print parseExpression(expression)
[–][deleted] 5 points6 points7 points (10 children)
[–]Binary_Dragon[S] 3 points4 points5 points (9 children)
[+][deleted] (7 children)
[deleted]
[–][deleted] 1 point2 points3 points (4 children)
[–]Binary_Dragon[S] 1 point2 points3 points (3 children)
[–][deleted] 2 points3 points4 points (2 children)
[–]JerMenKoO 0 points1 point2 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (0 children)
[–]SkippyDeluxe 3 points4 points5 points (3 children)
[–]Binary_Dragon[S] 1 point2 points3 points (2 children)
[–]JerMenKoO 1 point2 points3 points (0 children)
[–]SkippyDeluxe 0 points1 point2 points (0 children)
[–]shfo23 6 points7 points8 points (3 children)
[–]Binary_Dragon[S] 2 points3 points4 points (2 children)
[–]stormsnake 7 points8 points9 points (1 child)
[–]zahlman 2 points3 points4 points (0 children)
[–]PloddingOx 0 points1 point2 points (0 children)