Оценки математических выражений в Python

Я хочу обозначить данное математическое выражение в дереве синтаксического анализа следующим образом:

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

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

есть ли чистом Python способ сделать это? Как передача в виде строки Python, а затем вернуться в виде дерева, как указано выше.

спасибо.

5 ответов


да, питон 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)))'

несколько рамок парсер на Python; некоторые из них PLY и pyparsing. Нед Батчелдер имеет довольно полный список.


существует много хороших, установленных алгоритмов для разбора математических выражений, подобных этому. Один особенно хороший-Дийкстры алгоритм шунтирования, который можно использовать для создания такого дерева. Я не знаю конкретной реализации в Python, но алгоритм не особенно сложен, и это не должно занять слишком много времени, чтобы взорвать его.

кстати, более точный термин для дерева вы строите-это дерева или абстрактное синтаксическое дерево.


Я не знаю способа "чистого python" сделать это, который уже реализован для вас. Однако вы должны проверить ANTLR (http://www.antlr.org/) это парсер с открытым исходным кодом лексер и имеет API для ряда языков, включая python. Также на этом сайте есть несколько отличных видеоуроков, которые покажут вам, как сделать именно то, что вы просите. Это очень полезный инструмент, чтобы знать, как использовать в целом.


вы можете сделать это с помощью модуля Python ast.

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

теоперация - наша математическая операция, которую мы хотим оценить, мы используем isinstance, чтобы узнать тип, если это число, если его двоичный оператор(+,*,..). Вы можете прочитать на https://greentreesnakes.readthedocs.io/en/latest/tofrom.html, как работает ast

и для того, чтобы метод работал, мы должны использовать: evaluate(ast.parse(theoperation, mode='eval').тело)

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