在Python中评估数学表达式

时间:2011-02-19 07:23:19

标签: python parsing math binary-tree mathematical-expressions

我想将给定的数学表达式标记为这样的解析树:

((3 + 4 - 1) * 5 + 6 * -7) / 2

                          '/'
                        /     \
                       +        2
                    /     \
                  *         *
                /   \     /   \
               -     5   6     -7
             /   \
            +     1
          /   \
         3     4

有没有纯Python方法可以做到这一点?就像将字符串作为字符串传递给Python然后像上面提到的那样返回树。

感谢。

5 个答案:

答案 0 :(得分:9)

是的,Python ast模块提供了执行此操作的工具。您必须查找您的Python版本的确切界面,因为ast模块似乎经常更改。

特别是,ast.parse()方法对您的应用程序有所帮​​助:

>>> import ast
>>> ast.parse("(1+2)*3", "", "eval")
<_ast.Expression object at 0x88950>
>>> ast.dump(_)
'Expression(body=BinOp(left=BinOp(left=Num(n=1), op=Add(), right=Num(n=2)), op=Mult(), right=Num(n=3)))'

答案 1 :(得分:3)

Python存在几个解析器框架;一些常见的是PLYpyparsing。 Ned Batchelder有pretty complete list

答案 2 :(得分:1)

有许多好的,已建立的算法可用于解析像这样的数学表达式。一个特别好的是Dijkstra的shunting-yard algorithm,它可以用来制作这样一棵树。我不知道Python中的特定实现,但算法并不是特别复杂,并且不应该花太长时间来鞭打它。

顺便说一下,您构建的树的更精确的术语是parse treeabstract syntax tree

答案 3 :(得分:1)

您可以使用Python ast模块执行此操作。

https://docs.python.org/3.6/library/ast.html

操作是我们想要评估的数学运算,我们使用isinstance来了解它的类型,如果它是一个数字,如果它是一个二元运算符(+,*,..)。你可以在https://greentreesnakes.readthedocs.io/en/latest/tofrom.html阅读,以及如何工作

为了使方法有效,我们可以使用:evaluate(ast.parse(theoperation,mode ='eval')。body)

def evaluate(theoperation): 
    if (isinstance(theoperation, ast.Num)):
        return theoperation.n
    if (isinstance(theoperation, ast.BinOp)):
        leftope= evaluate(theoperation.left)
        rightope=evaluate(theoperation.right)   
        if (isinstance(theoperation.op, ast.Add)):
            return left+right
        elif (isinstance(theoperation.op, ast.Sub)):
            return left-right
        elif (isinstance(theoperation.op, ast.Mult)):
            return left*right
        elif (isinstance(theoperation.op, ast.Div)):
            return left/right
        elif (isinstance(theoperation.op, ast.Pow)):
            return left**right

答案 4 :(得分:0)

我不知道采用“纯python”的方法,已经为你实现了。但是你应该查看ANTLR(http://www.antlr.org/)这是一个开源解析器和词法分析器,它有一个包含python在内的多种语言的API。此网站还有一些很棒的视频教程,可以向您展示如何正确地完成您的要求。这是一个非常有用的工具,知道如何使用。