If I define a symbolic expression inside a function, how do I evaluate that expression using .subs()
outside that function. The following code demonstrates the issue:
import sympy as sp
def myFun():
x = sp.symbols("x", positive = True)
y = 3*x
return y
expr = myFun()
print(expr.subs({x:10}))
Running the code above gives NameError: name 'x' is not defined
.
How can I perform this evaluation? Two things I could think of is declaring x
to be a global variable using global x
inside myFun()
. However, I want to avoid this method. Another way is to lambdify
the expression in myFun()
before returning the expression. But I would prefer not to use this method because in the real problem I am working with, I have multiple variables in my expression and would like to substitute only some of the variables at one stage, and the remaining variables at a later stage. Would you adopt one of the two approaches I mentioned or is it possible to evaluate the expression using .subs()
using some other approach?
CodePudding user response:
@cards answer is not going to work, the reason is that you have defined x
to be positive, instead when calling print(expr.subs({'x':10}))
the string 'x'
will generate a generic symbol, without assumptions.
You either create your symbols outside of the function, like this:
import sympy as sp
x = sp.symbols("x", positive = True)
def myFun():
y = 3*x
return y
expr = myFun()
print(expr.subs({x:10}))
# out: 30
Or you can retrieve the symbols that make up a symbolic expression with the free_symbol
attribute, like this:
import sympy as sp
def myFun():
x = sp.symbols("x", positive = True)
y = 3*x
return y
expr = myFun()
x = expr.free_symbols.pop()
print(expr.subs({x:10}))
# out: 30
CodePudding user response:
Let's create an expression with two symbols in it:
In [44]: x, y = symbols('x, y')
In [45]: expr = sin(y) x**2
Suppose that we only have the expression as a local variable. We can find the symbols it contains using free_symbols
. We can use that to build a dict that maps symbol names (as strings) to the symbols themselves:
In [46]: expr.free_symbols
Out[46]: {x, y}
In [47]: syms = {s.name: s for s in expr.free_symbols}
In [48]: syms
Out[48]: {'y': y, 'x': x}
This mapping is important because different symbols with the same names but different assumptions are not interchangeable. With that we can substitute the symbol whose name is 'x'
like this:
In [49]: expr.subs(syms['x'], 2)
Out[49]: sin(y) 4
CodePudding user response:
x
as a Symbol
object is only declared in the function's body, so it's not accessible from the outside. Use 'x'
as a string.
x = list(expr.free_symbols)[0]
print(expr.subs({x: 2}))