Reputation: 1619
I am new to Python objects and have a lot of questions. I need to pass a function to my object, and then evaluate the function. The code is similar to this:
from sympy import var
class eval:
def __init__(self, M):
self.M = M
def fun(self, x):
M = self.M
print M(x)
x = var('x')
ak = eval(x+2)
ak.fun(x)
This is the error:
TypeError
Traceback (most recent call last)
(ipython-input-1-b7ef311bd1f0> in <module)()
12
13 ak = eval(x+2)
---> 14 ak.fun(x)
(ipython-input-1-b7ef311bd1f0) in fun(self, x)
7 def fun(self, x):
8 M = self.M
----> 9 print M(x)
10
11 x = var('x')
TypeError: 'Add' object is not callable
Upvotes: 2
Views: 7812
Reputation: 6549
I am new to Python objects...
Having questions is great, but the objects and classes behind SymPy are quite complex and learning the basics of the Python object model before delving in such a library is strongly encouraged.
There are many issues with the suggested code:
eval
is build-in so it is bad style to overwrite it SymPy does not provide new syntax for creating python functions. Especially, (x+2)(4)
is not going to give you 6
. If you want this just write myfun = lambda _: _+2; fun(4)
without using SymPy.
x+2
is a SymPy object (Add(Symbol('x')+Integer(2))
), not some python AST. You can substitute x
for something else with (x+2).subs(x,y)
but you can not expect the library to magically know that you have something special in mind for Symbol('x')
when you write (x+2)(4)
. You can as well write blah = Symbol('random_string'); (blah+2)(4)
.
var
is a helper function used to create Symbol
objects, but it is meant for interactive use in the interpreter. Do not use it in library code because as a side effect it injects global variables in the namespace. Just use Symbol('x')
.
x+2
being callableIn 0.7.2 recursive calling was implemented. What this means is that you can create a SymPy Expr
tree that contains unevaluated symbolic objects and apply the whole tree on another object, the calls propagating inwards until all unevaluated objects are substituted with evaluated ones. I guess the above description is not clear so here is an example:
You want to create a differential operator object D
which can do the following:
>>> op = g(y)*D # where g is Function and y is Symbol
>>> op(f(x))
g(y)*f(x).diff(x)
The way this works is to go down the tree (Mul(g(y), D)
in this case), skip evaluated symbolic objects and evaluate unevaluated symbolic objects.
Because a lot of SymPy's users start using it before reading about the data model this caused a lot of confusion, so we moved the recursive calling scheme to the rc
method. In 0.7.3 (x+2)(4)
will raise errors again.
Upvotes: 10
Reputation: 414835
Your code already can pass a function to the object. Functions are first-class citizens in Python you can pass them as any other object. The issue might be with your sympy
version. Compare:
>>> import sympy
>>> sympy.__version__
'0.7.1.rc1'
>>> from sympy.abc import x
>>> (x + 2)(x)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'Add' object is not callable
And:
>>> import sympy
>>> sympy.__version__
'0.7.2'
>>> from sympy.abc import x
>>> (x + 2)(x)
x + 2
i.e., the same code works on 0.7.2
but it fails on 0.7.1rc1
version.
Upvotes: 1
Reputation: 7052
There is couple issues with this.
Try this:
class Eval(object):
def __init__(self,m):
self.M = m
def fun(self,x):
print self.M(x)
x = var('x')
ak = Eval(x+2)
ak.meth(x)
x + 2
HTH
Upvotes: 1