Проверка, существует ли не целое число в строке во время eval()
Приведен ввод различных схем уравнений в скобках в виде строки, например '(3-7)/5'
Я смотрю, чтобы проверить, будет ли на каком-либо этапе его оценки содержать нецелое число.
Например, '(3/2)+1'
немедленно содержит float
и остается float
при полной оценке это существо 2.5
, Но что-то вроде '(5/2)*2'
кратко является числом с плавающей точкой, а затем может быть оценено как целое число, или, eval()
функция, '(4/2)+3'
после вычисления будет число с плавающей запятой, даже если во время оценки не существует нецелого числа.
Единственное, о чем я мог думать, пытаясь решить эту проблему, - это искать строку для /
оператор, а затем найти наименьший набор скобок, который будет включать это деление. Таким образом, для '(2+1)/4'
сначала нужно будет оценить 2+1
а затем может проверить на нецелое деление...
Какие-нибудь мысли?
1 ответ
К сожалению, есть слишком много вещей, которые могут привести к таким ценностям. Например **
может быть использован для вычисления квадратных корней и, как правило, содержимое передается eval
может быть что угодно.
Я верю, используя eval
это не очень хороший подход. Вы могли бы использовать ast.parse
функция, чтобы получить AST (абстрактное синтаксическое дерево), которое представляет выражение, а затем написать свой собственный простой интерпретатор для его оценки. В этом переводчике вы можете делать все проверки, которые вы хотите на каждом этапе.
Вы бы написали что-то вроде:
from ast import *
def simple_expr_eval(expr):
if not isinstance(expr, Expression):
raise TypeError('should be an expression')
return simple_eval(expr.body)
def simple_eval(expr):
handlers = {
BinOp: simple_eval_binop,
UnaryOp: simple_eval_unaryop,
Num: simple_eval_number,
# ...
}
return handlers[type(expr)](expr)
def simple_eval_binop(binop):
if binop.op is Mult:
left = simple_eval(binop.left)
right = simple_eval(binop.right):
return left * right
elif binop is Div:
# here you could check whether left/right produces a floating point...
raise ValueError('Floating operation during evaluation')
# ...
Это немного работы, но на самом деле не так много, если вы хотите работать только с простыми выражениями. В этих функциях вы можете упростить / поменять местами узлы, чтобы изменить способ вычисления выражения.
Вы также должны проанализировать код, указав eval
режим оценки (т.е. eval(your_expr, '<fake-filename>', 'eval')
).