我正在用 Python 编写一个计算器(作为练习),我想知道一点。
该程序将输入拆分为数字和运算符列表。然后计算结果如下:
import operator
ops = {'+' : operator.add, # operators and corresponding functions
'-' : operator.sub,
'*' : operator.mul,
'/' : operator.truediv,
'%' : operator.mod}
precedence = [['*', '/', '%'], ['+', '-']] # order of precedence for operators
def evaluate(exp):
for oplist in precedence: # search for operators first in order of precedence
for op in exp: # then from left to right
if op in oplist:
index = exp.index(op)
result = ops[op](exp[index - 1], exp[index + 1])
# compute the result of the operation
exp[index - 1:index + 2] = [result]
# replace operation and operands with result
return exp[0]
# for example,
evaluate([2, '+', 3, '+', 4, '+', 5])
# should return 14
该函数按优先级从左到右的顺序查找算术运算符列表,当找到这样的运算符时,它会调用相邻列表元素(操作数)上的相应函数,并替换列表中的运算符和操作数列出操作结果。执行完所有操作后,列表将包含一个元素 - 计算结果。
但是,此函数的行为并不像预期的那样。问题(我认为)是这个函数在迭代列表时修改了列表(通过分配给切片)。我已经找到了 here 这个问题的解决方案(通过在每次修改列表时重新启动内部
for
循环),但是提供解决方案的人似乎认为通常应该有更好的方法来完成任何需要的.我想知道是否有更好的方法来实现这个算法来避免奇怪的“重新启动循环”的事情。
感谢您的任何想法!
最佳答案
我想我会以不同的方式去做,并使用递归函数。弹出操作并用它们的评估结果替换它们。
import operator
ops = {
'+' : operator.add,
'-' : operator.sub,
'*' : operator.mul,
'/' : operator.truediv,
'%' : operator.mod,
}
precedence = [
set(['*', '/', '%']),
set(['+', '-']),
]
def evaluate(expr):
# if len == 3 then just return result of expression
if len(expr) == 3:
l, op, r = expr
return ops[op](l, r)
else:
for op_list in precedence:
for op in expr:
if op in op_list:
# find index of first operation
idx = expr.index(op)-1
# pop off and evaluate first matching operation in expr
result = evaluate([expr.pop(idx) for i in range(3)])
# insert result back into expr
expr.insert(idx, result)
return evaluate(expr)
关于python - 有没有更好的方法来实现这一点?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7005732/