2

I'm writing a code in Python which can be used to solve equations. The user must first input a code via a raw_input(), which will then be used to calculate y for every x in a loop with eval(), like so:

#some imports (math) and other irrelevant code
Code = raw_input('please enter your equation')
Low = raw_input('please enter the lowest number in the domain')
High = raw_input('please enter the highest number in the domain')
X = Low
While X <= High:
    Y = eval(code)
    #complicated code to solve equation
    X += #number depending on the amount of decimals
#simpler code to print the result

The problem is that parsing the input code using eval() for every loop is extremely slow. Is there a way to parse the code only once and then use it as a function in the rest of the program?

manlio
  • 18,345
  • 14
  • 76
  • 126
inecrafter
  • 57
  • 7

3 Answers3

3

You can compile the expression in advance using compiler.compile() (deprecated since Python v2.6).

With Python 3.x:

Also take a look at: Python: Way to speed up a repeatedly executed eval statement?

EDIT

Some examples:

>>> expr = 'x*x + 2*x + 1'
>>> expr_obj = compile(expr, '', 'eval')
>>> x = 1
>>> y = eval(expr)

and now

>>> y
4
>>> x = 2
>>> y = eval(expr)
>>> y
9

compile is a lower level version of eval (and exec). It doesn't evaluate/execute your expression/statement but returns a code object that can do it.


PS as a general rule when using eval on user submitted strings you must be very careful about what you accept (it's a potential security hole).

Community
  • 1
  • 1
manlio
  • 18,345
  • 14
  • 76
  • 126
  • I might be doing something wrong, but compile(code) returns the location of the code instead of the evaluation. – inecrafter Feb 10 '15 at 12:57
  • `compile` doesn't evaluate your expression but returns a code object that can do it. I've added an example. – manlio Feb 10 '15 at 14:23
  • Thank you, that reduced calculation times significantly! – inecrafter Feb 10 '15 at 14:59
  • To give you an example: it can now calculate all 128 intersections of tan(x**2)=y with the x-axis in just 3300 miliseconds accurate to 7 decimals on my 1.4Ghz iPad. – inecrafter Feb 10 '15 at 15:10
1

if the equation in code doen't need any reference to X, then you could move Y = eval(code) outside the loop. Otherwise you need it at this position to access X and its current value.

wolfrevo
  • 6,651
  • 2
  • 26
  • 38
  • If the equation doesn't reference X, then the value of Y would be constant, and there would be no need for the loop in the first place. It looks like the OP is trying to get a table of values of Y for different values of X, implying that Y *is* a function of X. – PaulMcG Feb 10 '15 at 18:50
0

If the user inputs the equation in terms of a single variable "X", then you can convert it to a function using Python's lambda keyword:

CodeAsFunction = eval('lambda X : ' + Code)

(For this to work, the user just enters the right-hand side of the equation, 3*X + 100, not Y = 3*X+100.)

Then in the body of your loop, you can call this function instead:

while X = High:
    Y = CodeAsFunction(X)
    ... etc. ...

Note, eval is now only being called once, to create the callable CodeAsFunction variable.

Of course, you must take care regarding security issues, as have already been mentioned by other posters.

PaulMcG
  • 62,419
  • 16
  • 94
  • 130