我想将给定的数学表达式标记为这样的解析树:
((3 + 4 - 1) * 5 + 6 * -7) / 2
'/'
/ \
+ 2
/ \
* *
/ \ / \
- 5 6 -7
/ \
+ 1
/ \
3 4
有没有纯Python方法可以做到这一点?就像将字符串作为字符串传递给Python然后像上面提到的那样返回树。
感谢。
答案 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存在几个解析器框架;一些常见的是PLY和pyparsing。 Ned Batchelder有pretty complete list。
答案 2 :(得分:1)
有许多好的,已建立的算法可用于解析像这样的数学表达式。一个特别好的是Dijkstra的shunting-yard algorithm,它可以用来制作这样一棵树。我不知道Python中的特定实现,但算法并不是特别复杂,并且不应该花太长时间来鞭打它。
顺便说一下,您构建的树的更精确的术语是parse tree或abstract 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。此网站还有一些很棒的视频教程,可以向您展示如何正确地完成您的要求。这是一个非常有用的工具,知道如何使用。