【问题标题】:Math Expression Evaluation数学表达式评估
【发布时间】:2010-12-05 10:46:03
【问题描述】:

实现一个接受字符串并根据运算符优先级输出其结果的python程序的最佳方法是什么(例如:“4+3*5”将输出19)。我搜索了解决这个问题的方法,但它们都太复杂了,我正在寻找一种(相对)简单的方法。

澄清:我需要比 eval() 稍微高级一点的东西 - 我希望能够添加其他运算符(例如最大运算符 - 4$2 = 4),或者,我对学术上的兴趣也比专业上的 -我想知道如何做到这一点。

【问题讨论】:

标签: python parsing math expression evaluation


【解决方案1】:

如果您“对学术感兴趣”,您想了解如何编写具有运算符优先级的解析器。

Simple Top-Down Parsing in Python 是一篇不错的文章,它构建了一个示例解析器来完全执行您想做的事情:评估数学表达式。

我强烈建议您尝试编写自己的第一个解析器——这是“啊,这就是它是如何工作的”时刻之一!

【讨论】:

  • 我快速浏览了一下,您链接到的文章似乎在 Python 中实现了解释器模式。
【解决方案2】:

这就是“eval”函数在 Python 中的作用。

result = eval(expression)

请注意,虽然它可以做更多的事情,主要是调用函数,所以为了安全起见,您应该确保它不能访问局部变量或全局变量。此外,您可以访问内置方法,包括棘手的 import,因此您还需要阻止对它的访问:

result = eval(expression, {'__builtins__': None}, {})

但这只是在您需要安全性的情况下,也就是说,如果您允许任何人输入任何表达式。

当然,既然你用这种方式阻止了所有 locla 变量的使用,那么你就没有任何变量要使用,所以你只需要传入那些应该在字典中访问的变量。

vars = {'__builtins__': None, 'x': x}
result = eval(expression, vars, {})

或类似的。

【讨论】:

  • 当 expression = "system.os(rm -rf )" 时出现 eval 的问题。如果您在 *nix 中以 root 身份运行它,那么机器就会繁荣。或者如果它是 Windows 等价物,特别是因为有太多人以管理员身份运行 Windows。
  • 仅当您已完成 from os import system 并且不提供 globals 和 locals 目录时。出于这个原因,我在我的示例中这样做了。
  • 里面的表达式,可以再次从os导入系统,然后使用。所以是的,我的例子只有在你已经从系统导入 os 时才有效,但是通过扩展我的表达式,你可以导入任何你想要的东西并使用它。
  • @Thomas:如果您在 Linux 环境中以 root 身份运行,或者在 Windows 环境中以管理员身份运行,那么您应该得到公正的结果。
  • @D.Shawley:那么可怜的用户没有以 root 身份运行并且只会丢失他自己的所有文件 - 他/她应该得到这样的结果吗?
【解决方案3】:

另一种可能是看Pyparsing,它是一个通用的解析器构建器。它比您需要的更强大,但实施起来可能更快。

【讨论】:

  • pyparsing wiki (pyparsing.wikispaces.com) 包含几个算术表达式解析器示例 -fourFn.py 和 simpleArith.py。即使您不使用 pyparsing,fourFn.py 也可能对此类解析器如何实现运算符优先级有所启发。
  • 我刚刚意识到 OP 想要添加其他运算符。 simpleArith.py 展示了如何添加阶乘 (!) 运算符 - evalArith.py(在页面底部)扩展了 simpleArith.py 并展示了如何评估解析的值。
【解决方案4】:

我对 Python 和任何极其 Pythonic 的方法都不是很熟悉,但您可以查看在 Gang of Four 书中定义的 Interpreter pattern。它是为处理“语言”而设计的,数学表达式确实遵循具有规则的特定语言。其实维基百科上的例子其实就是一个RPN计算器的Java实现。

【讨论】:

  • 所以他们的调用现在也在解析“模式”?这一定是计算机科学中被滥用最多的词……
  • @Thomas:这并不比泛型解析更具体,真的。我的意思是,所有解析都涉及某种“句子”;并且任何体面的解析器都是干净/可理解的,至少在某种形式上是这样。 (以递归下降为例。)另外,s/their/they're :P
  • 解释器是一个原始的 GOF 模式。该示例是一个简单正则表达式库的(非常)高级设计。它建议使用 AST 来进行语言描述,本质上,而不是(也许以及)用于解析的输入。应该适用于递归下降,但它不包括如何做到这一点。真的,我认为它不应该出现在书中——你只需要一个正则表达式库和(也许)一个表达式评估器库,而不是一个模式。除此之外,是 lex、yacc 和朋友们的时候了。
  • @Noldorin:“所以他们的调用现在也在解析“模式”?”我喜欢你这样说,好像 GoF 的书是在过去几个月里发布的。解释器模式不仅仅是解析。它定义了一种经过验证的读取数据并以可用方式对其进行结构化的方法。我见过其他导致乱码的解析尝试。
  • 嗯 - 我可能需要撤回“不应该是模式声明”。我一直在想其他的例子。 XML 解析器、嵌套块二进制文件处理程序、声明性事件流处理程序 - 例如游戏实体 AI 和复杂的可配置 GUI 控件,...
【解决方案5】:

【讨论】:

    【解决方案6】:

    此收据为您的问题提供了正确答案:

    http://code.activestate.com/recipes/496746-restricted-safe-eval/

    它允许您评估不会损害您的计算机或程序的有限语句。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 2010-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多