Разберите выражение через AST и разрешите только числа и арифметические операции. Деление на ноль обработайте отдельно, возвращая -1.
Реализовать функцию‑вычислитель арифметического выражения
Разберите выражение через AST и разрешите только числа и арифметические операции. Деление на ноль обработайте отдельно, возвращая -1.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Создайте функцию, принимающую строку, содержащую простое математическое выражение (например: "2+3"). Функция должна вычислить значение выражения и вернуть его. Если в процессе вычисления происходит деление на ноль, функция должна вернуть -1.
Пример: Ввод: "2+3" Вывод: 5
Ответ
Разберите выражение через AST и разрешите только числа и арифметические операции. Деление на ноль обработайте отдельно, возвращая -1.
Не используйте eval для пользовательского ввода. Здесь поддерживаются +, -, *, /, скобки и унарные знаки:
import ast
import operator
OPS = {ast.Add: operator.add, ast.Sub: operator.sub,
ast.Mult: operator.mul, ast.Div: operator.truediv}
def calculate(text):
if len(text) > 200:
raise ValueError('Слишком длинное выражение')
tree = ast.parse(text, mode='eval')
if sum(1 for _ in ast.walk(tree)) > 60:
raise ValueError('Слишком сложное выражение')
def visit(node):
if isinstance(node, ast.Constant) and type(node.value) in (int, float):
return node.value
if isinstance(node, ast.BinOp) and type(node.op) in OPS:
return OPS[type(node.op)](visit(node.left), visit(node.right))
if isinstance(node, ast.UnaryOp) and isinstance(node.op, (ast.UAdd, ast.USub)):
value = visit(node.operand)
return value if isinstance(node.op, ast.UAdd) else -value
raise ValueError('Недопустимое выражение')
try:
return visit(tree.body)
except ZeroDivisionError:
return -1
Вызовы функций, атрибуты и переменные запрещены. Синтаксические ошибки не маскируются значением -1.