0

I declare a variable, define an expression using the variable

from sympy import *
x = symbols ('x')
f = 2 * x 

and then assign a value to the variable

x = 42

How can I substitute the variable in the expression by its current value? For obvious reasons

f.subs (x, x) 

does not work. I know that I can use a different variable

xx  = 42
f.subs (x, xx)

but ...

Nobody likes to get compared to their new girlfriend's ex, but in Matlab you could simply write subs (f) which would be the equivalent to SymPy's f.subs () without any parameters, to substitute all intermediately assigned variables.

  • 1
    Well, sympy works differently. Sympy has been carefully created to fit into an existing Python ecosystem. In your case, you could try `f.subs ('x', x)`. Note that if you write `x = symbols('x')`, and then `x = ....`, you remove your direct access to the symbol. Matlab is a dedicated environment; each tool has its strong and weak points. Feel free to choose the one that best fits your workflow. By the way, a function that loops through an expression, looks up the variable names into the globals and does substitutions, wouldn't be that hard to write. – JohanC Mar 25 '22 at 11:58
  • Does this answer your question? [Sympy "global" substitution](https://stackoverflow.com/questions/9560362/sympy-global-substitution) – JohanC Mar 25 '22 at 12:00
  • 2
    I answered a similar question yesterday, https://stackoverflow.com/a/71593718/901925 – hpaulj Mar 25 '22 at 14:55
  • Johan, thank you, `f.subs ('x', x)` makes my life a bit easier. In aaguirre's [GlobalSubs](https://stackoverflow.com/questions/9560362/sympy-global-substitution) I still have to list all the variables I want to substitute. I am still dreaming of an automatic `f.subs()` that substitutes **all** currently assigned variables. But as you said, as soon as I understand a bit more about sympy, I will try to write that function ... – Jörg J. Buchholz Mar 25 '22 at 16:14

1 Answers1

3

per above,

>>> f = x**2
>>> x = 42
>>> def update(e):
...     d = globals()
...     return e.xreplace({x: eval(x.name, d) for x in e.free_symbols})
>>> Eq(f, update(f))
x**2 = 1764
smichr
  • 16,948
  • 2
  • 27
  • 34
  • Wow, great, thanks a lot, Chris! Now give me a few days to understand what you did there ... – Jörg J. Buchholz Mar 25 '22 at 17:04
  • First question: what does `d = dir()` do? It seems to work without it. – Jörg J. Buchholz Mar 25 '22 at 17:09
  • Is the use of `globals()` as the second `eval` parameter necessary? With my limited knowledge, I cannot imagine any situation in this use case where omitting the reference to the current module namespace could be dangerous or critical. – Jörg J. Buchholz Mar 25 '22 at 18:22
  • 1
    I updated the code so `d` is used (and assigned `globals()`. Since you are passing the value to function it is safe. but if someone else had access to it I suppose they could name a symbol with some nefarious name which, when evaluated, would to bad things. – smichr Mar 25 '22 at 20:42