1

I have a list of functions as strings:

["y + x + 3", "x**2 + y**2 - 17"]  # 2 functions in list

I have a list of Sympy Symbol objects (basically variables) whos .name attribute cooresponds to the variables names in the function strings:

[Symbol(x), Symbol(y)]
# list element 0's .name attribute is "x" 

I found that Python have a neat function called eval() which can evaluate strings, for example:

x = 1
eval("x + 3") # Result should be 4

Basically this is what I want to do with my functions strings. However, since this is a dynamic implementation I don't have variables defined on a line above eval() in my program, they are in a list instead. For example, in the example above x is defined as 1, so then the eval() function can use it.

But I have my variables in a list, not defined as a variable in the scope of my function. How could I use the eval() function and utilize my list of variables?

5 Answers 5

3

eval takes local variables as third argument(reference), so you can do this:

from sympy import Symbol
zs = [Symbol('x'), Symbol('y')]
eval('x+y', None, dict([z.name, z] for z in zs))

However, maybe you should use parse_expr which is part of SymPy.

from sympy import Symbol
from sympy.parsing.sympy_parser import parse_expr
zs = [Symbol('x'), Symbol('y')]
parse_expr('x+y', local_dict=dict([z.name, z] for z in zs))
Sign up to request clarification or add additional context in comments.

1 Comment

I'll take a look at the parse_expr method. Right now I have it working with eval() with your advice. But maybe the other one it better.
2

How about this, and you can wrap following codes of replacing and eval in your symbol class(through inheriate).

import ast

x = 5
y = 6

function_str = "y + x + 3"
function_str = function_str.replace('x', '{x}')
function_str = function_str.replace('y', '{y}')

print(ast.literal_eval(function_str.format(x=x, y=y)))
# 14

Always remember that using eval is "EVAL" 'cause you should not trust the string passed in, listeral_eval is safer.

Comments

1

Look at full definition of eval (expression[, globals[, locals]])

You can substitute globals/locals on eval.

E.g.

eval("x + 3", {"x":1}) # Result should be 4

How could I use the eval() function and utilize my list of variables?

You have 2 namespaces and you can do everything you want with them.

Comments

1

You could do something along these lines:

import math

symbols = {'sqrt': math.sqrt, 'x': 5, 'y': 6}

func_strings = ["y + x + 3", "x**2 + y**2 - 17", "sqrt(1764)"]

for expression in func_strings:
    result = eval(expression, {'__builtins__': None}, symbols)
    print('{} -> {}'.format(expression, result))

Output:

y + x + 3 -> 14
x**2 + y**2 - 17 -> 44
sqrt(1764) -> 42.0

Comments

-1

Best way to do it in my opinion would be to add all of the variables to locals. Then you can reference them by name in eval. Example:

symbols = [Symbol(x), Symbol(y)]
locals().update({symbol.name:symbol for symbol in symbols})

eval("x+y") # Should return the value of x+y

1 Comment

The documentation clearly states that the dictionary locals() returns should no be updated because doing so is unreliable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.