编写后缀表达式求值器并不难。以下是一个工作示例。 (也available在github上。)
import operator
import math
_add, _sub, _mul = operator.add, operator.sub, operator.mul
_truediv, _pow, _sqrt = operator.truediv, operator.pow, math.sqrt
_sin, _cos, _tan, _radians = math.sin, math.cos, math.tan, math.radians
_asin, _acos, _atan = math.asin, math.acos, math.atan
_degrees, _log, _log10 = math.degrees, math.log, math.log10
_e, _pi = math.e, math.pi
_ops = {'+': (2, _add), '-': (2, _sub), '*': (2, _mul), '/': (2, _truediv),
'**': (2, _pow), 'sin': (1, _sin), 'cos': (1, _cos), 'tan': (1, _tan),
'asin': (1, _asin), 'acos': (1, _acos), 'atan': (1, _atan),
'sqrt': (1, _sqrt), 'rad': (1, _radians), 'deg': (1, _degrees),
'ln': (1, _log), 'log': (1, _log10)}
_okeys = tuple(_ops.keys())
_consts = {'e': _e, 'pi': _pi}
_ckeys = tuple(_consts.keys())
def postfix(expression):
"""
Evaluate a postfix expression.
Arguments:
expression: The expression to evaluate. Should be a string or a
sequence of strings. In a string numbers and operators
should be separated by whitespace
Returns:
The result of the expression.
"""
if isinstance(expression, str):
expression = expression.split()
stack = []
for val in expression:
if val in _okeys:
n, op = _ops[val]
if n > len(stack):
raise ValueError('not enough data on the stack')
args = stack[-n:]
stack[-n:] = [op(*args)]
elif val in _ckeys:
stack.append(_consts[val])
else:
stack.append(float(val))
return stack[-1]
用法:
In [2]: from postfix import postfix
In [3]: postfix('1 2 + 7 /')
Out[3]: 0.42857142857142855
In [4]: 3/7
Out[4]: 0.42857142857142855
够奇怪的,但是'literal_eval'仅支持'和'-',只有在整数'+。其他操作符生成相同的“格式错误...”错误。测试py3.5。 – robyschek
@robyschek我无法重现与浮动失败('ast.literal_eval('1.2 + 2.3')'工作正常)。但你说得对,并非所有的运营商都有可能。我添加了另一种方式 - 实现(很多)更多功能。 – MSeifert
@MSeifert安装了'numpy'。在导入'numpy'和'numexpr'之后,它会显示'ModuleNotFoundError:No module named'numexpr''。我试过重新安装。 – Aamri