Вы можете проанализировать выражение с помощью ast.parse
.
>>> import ast
>>> expr = ast.parse("3 + 5", mode="eval")
Затем вы можете проанализировать получившееся дерево синтаксического анализа. В данном конкретном случае вы заботитесь о теле выражения.
>>> expr
<_ast.Expression object at 0x10992c438>
>>> expr.body
<_ast.BinOp object at 0x10a926320>
Этот объект имеет интересующие атрибуты: left
, op
и right
. Вы посмотрите на оператор
>>> expr.body.op
<_ast.Add object at 0x10a91a208>
, чтобы решить, как обрабатывать операнды.
>>> expr.body.left.n + expr.body.right.n
8
Таким образом, простая рекурсивная функция, которая может обрабатывать умножение и сложение, может выглядеть как
def evaluate_expr(expr):
if isinstance(expr, ast.Expression):
return evaluate_expr(expr.body)
elif isinstance(expr, ast.Num):
return expr.n
elif isinstance(expr, ast.BinOp):
op = expr.op
left = evaluate_expr(expr.left)
right = evaluate_expr(expr.right)
if isinstance(op, ast.Add):
return left + right
elif isinstance(op, ast.Mult):
return left * right
raise ValueError(f"Can't evaluate {expr}")
e = ast.parse("3 + 5 * 2", mode="eval")
print(evaluate_expr(e.body)) # Outputs 13
См. Документацию к модулю ast
, чтобы узнать, какие еще узлы могут отображаться в дереве, чтобы вы могли адаптировать evaluate_expr
для обработки других операций, скобок и т. Д. c. ast.dump
также полезен для изучения того, как анализируется выражение.
>>> ast.dump(e, annotate_fields=False)
'Expression(BinOp(Num(3), Add(), BinOp(Num(5), Mult(), Num(2))))'
Это ясно показывает, что синтаксический анализатор обрабатывает приоритет: 3 + 5 * 2
не 3 + 5
с результатом, умноженным на 2, а скорее 3
плюс результат 5 * 2
(более низкие узлы имеют более высокий приоритет, поскольку дерево оценивается снизу вверх).
Это предполагает, что ваш ввод фактически является действительным выражением Python. Если нет, вам нужно будет написать свой собственный синтаксический анализатор, но как только у вас есть дерево синтаксического анализа, оценка этого дерева происходит аналогичным образом (хотя узлы дерева - это все, что вы создаете в своем синтаксическом анализе, не обязательно ast.Bin
и др. узлы, созданные ast.parse
).