That's basically the same thing as my solution, since Function('f') is
basically just class f(Function):pass, except my way automatically
works with all the methods of sin because it subclasses it directly.

Regarding printing, you can add the various printing methods to the
class (see http://docs.sympy.org/0.7.2/modules/printing.html).  It
boils down to writing some methods on the class.

You could also just call it sin, like

class sin(sin):
    ...

You would need to handle your namespaces properly to do this (i.e.,
use sympy.sin to get the original sin), but it should work just fine
otherwise (although maybe it won't, because unfortunately there are
some things that are incorrectly using the name of the class to
recognize it, so if something doesn't work with that, just let us
know).

Aaron Meurer


On Sat, Jun 1, 2013 at 7:25 PM, Lucas Wilkins
<[email protected]> wrote:
> Is there some reason not to do this? (except for the way it prints)
>
> hold = Function("Hold")
>
> def release(expr):
>     return expr.replace(hold, Id)
>
> print sin(pi), sin(hold(pi)), release(sin(hold(pi)))
>
> :L
>
> On Saturday, 1 June 2013 05:08:53 UTC+1, Aaron Meurer wrote:
>>
>> 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.
>
>

-- 
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.


Reply via email to