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
> --
> 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
sympy+un...@googlegroups.com.
> To post to this group, send email to
sy...@googlegroups.com.
> Visit this group at
http://groups.google.com/group/sympy?hl=en-US.
> For more options, visit
https://groups.google.com/groups/opt_out.
>
>