Home > OS >  In sympy, evaluating an expression using .subs() when that expression has been defined in another fu
In sympy, evaluating an expression using .subs() when that expression has been defined in another fu

Time:09-06

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}))
  • Related