2016-12-06 9 views
1

У меня есть класс с именем NumApprox, он берет строку в качестве ввода (математическое выражение, содержащее переменную «x»), и все методы в нем просто разные approachs интегрировать математическое выражение дано численное значение «х»Python 3.5 Как я могу избавиться от eval в моей функции класса

ожидаемые примеры ввода:

input = " x ** 2 * log(x) " 

    input = "1/sqrt(2*pi) * exp(- x **2/2) " 

мне было интересно, как я могу выделить и взять под контроль «х» переменной, представленной во входной строке и использовать его из любого места в моем классе без функции eval.

Это то, что я сделал, но мне не нравится эта функция «eval» и дается мое ограниченное знание классов Python ... Я хотел бы знать, есть ли лучшая альтернатива «eval», ?

from math import pi, sqrt, exp, log 

class NumApprox: 

    def __init__(self, expr): 
     self.expr = expr 

    def pdf(self, x): 
     self.x = x 
     self.ev = eval(self.expr.replace('x', 'self.x')) 
     return self.ev 

    def integrate_rect_method(self, A, B, n): 
     ... 
+1

Если вы хотите оценить произвольные выражения, не прибегая к 'eval', вам, вероятно, придется начинать смотреть на какой-то парсер. – Iluvatar

+0

лучше использовать модули, такие как [SymPy] (http://www.sympy.org/) – furas

+0

Как вы думаете, что вы думаете, 'self.expr.replace ('x', 'self.x')' будет делать, когда 'expr' -' exp (x) '? – donkopotamus

ответ

2

Возможно использовать модуль SymPy

from sympy import * 
from sympy.parsing.sympy_parser import parse_expr 

x, y, z = symbols("x y z") 

input = " x ** 2 * log(x) " 

#expr = sympify(input) # `sympify` uses `eval` 
expr = parse_expr(input) 

print(expr) 
print(expr.subs({x:2})) 

input = "1/sqrt(2*pi) * exp(- x **2/2) " 

#expr = sympify(input) # `sympify` uses `eval` 
expr = parse_expr(input) 

print(expr) 
print(expr.subs({x:2})) 

результат:

x**2*log(x) 
4*log(2) 

sqrt(2)*exp(-x**2/2)/(2*sqrt(pi)) 
sqrt(2)*exp(-2)/(2*sqrt(pi)) 

Parsing

Basic Operations и Sympify

+0

Спасибо за предложение и демонстрацию, дадут ему попробовать и протестировать. Однако один быстрый вопрос: действительно ли модуль SymPy сильно полагается на evals для обработки произвольных выражений? – jwdasdk

+0

Я нашел только информацию, что 'sympify' использует' eval'. Если вам нужна дополнительная информация, вам нужно будет проверить исходный код - на странице SymPy есть ссылки на код. Если вы не хотите 'eval', тогда вам придется строить парсер - вы можете использовать [PLY] (http://www.dabeaz.com/ply/), но ему нужно больше работать. – furas