There have been many discussions on this sort of thing. There is a semi-standard way to do things by passing evaluate=False, like
In [6]: sin(pi, evaluate=False) Out[6]: sin(π) Not all SymPy classes support this though, and it's not easy to use it with things like xreplace. Another way is to bypass the constructor of the class, like In [7]: Basic.__new__(sin, pi) Out[7]: sin(π) You can write an algorithm that walks the expression tree and replaces sin(x) with Basic.__new__(sin, pi) farily easily. But probably the best way is to just subclass sin and disable evaluation In [1]: class noevalsin(sin): ...: @classmethod ...: def eval(cls, arg): ...: return ...: In [2]: noevalsin(pi) Out[2]: noevalsin(π) In [4]: noevalsin(x).diff(x) Out[4]: cos(x) (the diff shows that it does indeed act like sin otherwise). You can change the printing by adding some more methods to the class. You can then use replace to replace instances of sin with noevalsin In [8]: sin(x).replace(sin, noevalsin) Out[8]: noevalsin(x) In [9]: sin(x).replace(sin, noevalsin).subs(x, pi) Out[9]: noevalsin(π) This third option is better because any function that rebuilds the object will keep it as it is. With the other two, the rebuilding will do sin(pi) and it will go to 0. With this, the rebuild will do noevalsin(pi) and it will stay unevaluated. You could also abstract this logic into a helper function (or class or metaclass). One issue with all of these is that many algorithms come to rely on the invariants satisfied by the classes---in this case, that sin(pi) is never an object---and so they might fail on such expressions. An easy way to check this is to disable it in the SymPy source and run the tests. Finally, we often don't use best practices so that classes are subclassable (see https://code.google.com/p/sympy/issues/detail?id=3652). If you come across something that converts noevalsin back into regular sin, that's probably a bug, or it might mean that you need to define more methods on the class. For example, noevalsin(x).diff(x, x) will be -sin(x), not -noevalsin(x), because cos(x).diff(x) remains unchanged. Aaron Meurer On Fri, May 31, 2013 at 8:31 PM, Ben Lucato <[email protected]> wrote: > So in my ever growing quest to work with sympy, I have expressions like: > > y = 2*(x*sin(x) - sin(x) + cos(x))/cos(x)**2 > > with x values like pi/6 > > How do I substitute x into y without having evaluate automatically happen. > > i.e. I would like to be able to do something like: > > y.xreplace({x: pi/6}) >>>> 2*((pi/6)*sin(pi/6) - sin(pi/6) + cos(pi/6))/cos(pi/6)**2 > > > It doesn't need to be with xreplace, that's just what I've used here for > explaining my goal. > > Thanks! > > -- > You received this message because you are subscribed to the Google Groups > "sympy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/sympy?hl=en-US. > For more options, visit https://groups.google.com/groups/opt_out. > > -- You received this message because you are subscribed to the Google Groups "sympy" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/sympy?hl=en-US. For more options, visit https://groups.google.com/groups/opt_out.
