To substitute several values:
>>> from sympy import Symbol
>>> x, y = Symbol('x y')
>>> f = x + y
>>> f.subs({x:10, y: 20})
>>> f
30
Answer from Wesley on Stack Overflowsubs is slow
python - How can I substitute multiple symbols in an expression in SymPy? - Stack Overflow
python - In sympy, evaluating an expression using .subs() when that expression has been defined in another function - Stack Overflow
Sympy problem with subs
Videos
To substitute several values:
>>> from sympy import Symbol
>>> x, y = Symbol('x y')
>>> f = x + y
>>> f.subs({x:10, y: 20})
>>> f
30
The command x = Symbol('x') stores SymPy's Symbol('x') into Python's variable x. The SymPy expression f that you create afterwards does contain Symbol('x'), not the Python variable x.
When you reassign x = 0, the Python variable x is set to zero, and is no longer related to Symbol('x'). This doesn't have any effect on the SymPy expression, which still contains Symbol('x').
This is best explained in this page of the SymPy documentation: Gotchas and Pitfalls, Variables
What you want to do is f.subs(x,0), as said in other answers.
@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
EDIT (to accommodate comment):
I was just wondering but what if the expression had three variables, say
5*y + 3*x + 7*z? I tried the code you provided. The lineexpr.free_symbols.pop()only gives one of the variables - it givesx. Is there a way to usefree_symbolsto get all three variables?
free_symbols returns a set with all variables. If the expression is expr = 5*y + 3*x + 7*z, then expr.free_symbols returns {x, y, z}.
pop() is a method of Python's set: it returns the first element of a set.
To get all the variables of your expression you could try: x, y, z = expr.free_symbols, or x, y, z = list(expr.free_symbols). However, this creates the following problem: execute print(x, y, z) and you'll get something similar to: y z x. In other words, the symbols returned by expr.free_symbols are unordered. This is the default Python behavior.
Can we get ordered symbols? Yes, we can sort them alphabetically with : x, y, z = sorted(expr.free_symbols, key=str). If we now execute print(x, y, z) we will get x y z.
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
I'm trying to streamline a program to solve elements of a Jacobian matrix. Sympy is working for the most part, but there seems to be one bug.
J11 = diff(rN(1-N/B),N)
J11 r*(1 - N/B) - N*r/B
When I try to enter the variable name, it doesn't substitute the variable that I want.
( J11).subs(r,4) r*(1 - N/B) - N*r/B
However, the equation itself gives me the result I want.
(r*(1 - N/B) - Nr/B).subs(r,4) 4 - 8N/B
Any way to get this to work with the variable name?