我是Python对象的新手并且有很多问题。我需要将一个函数传递给我的对象,然后评估该函数。代码类似于:
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)
这是错误:
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
答案 0 :(得分:10)
我是Python对象的新手......
有问题很好,但SymPy背后的对象和类非常复杂,并且在强烈鼓励在钻研这样一个库之前学习Python object model的基础知识。
建议的代码存在许多问题:
eval
是内置的,因此覆盖它的风格很糟糕 SymPy 不提供了创建python函数的新语法。特别是(x+2)(4)
不会给你6
。如果你想要这个,只需写myfun = lambda _: _+2; fun(4)
而不使用SymPy。
x+2
是一个SymPy对象(Add(Symbol('x')+Integer(2))
),而不是一些python AST。您可以将x
替换为(x+2).subs(x,y)
的其他内容,但是当您编写Symbol('x')
时,您不能指望图书馆神奇地知道您在(x+2)(4)
时有一些特别的想法。你也可以写blah = Symbol('random_string'); (blah+2)(4)
。
var
是用于创建Symbol
个对象的辅助函数,但它用于在解释器中进行交互式使用。不要在库代码中使用它,因为作为副作用,它会在命名空间中注入全局变量。只需使用Symbol('x')
。
x+2
可以调用在0.7.2中实现了递归调用。这意味着您可以创建一个SymPy Expr
树,其中包含未评估的符号对象,并将整个树应用于另一个对象,调用向内传播,直到所有未评估的对象都被评估的对象替换。我想上面的描述并不清楚,所以这里有一个例子:
您想要创建一个差异运算符对象D
,它可以执行以下操作:
>>> op = g(y)*D # where g is Function and y is Symbol
>>> op(f(x))
g(y)*f(x).diff(x)
这种方法的工作方式是沿着树(在这种情况下为Mul(g(y), D)
),跳过评估的符号对象并评估未评估的符号对象。
因为很多SymPy的用户在阅读数据模型之前就开始使用它,这引起了很多困惑,所以我们将递归调用方案移到了rc
方法。在0.7.3 (x+2)(4)
中会再次出现错误。
答案 1 :(得分:1)
这有几个问题。
试试这个:
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
答案 2 :(得分:1)
您的代码已经可以将函数传递给对象。函数是Python中的一等公民,你可以像任何其他对象一样传递它们。问题可能出在您的sympy
版本上。比较:
>>> 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
和
>>> import sympy
>>> sympy.__version__
'0.7.2'
>>> from sympy.abc import x
>>> (x + 2)(x)
x + 2
即,相同的代码适用于0.7.2
,但在0.7.1rc1
版本上失败。