2

我是 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
4

3 回答 3

10

我是 Python 对象的新手...

有问题很好,但是 SymPy 背后的对象和类非常复杂,强烈建议在深入研究这样的库之前学习Python 对象模型的基础知识。

建议的代码有很多问题:

纯语言相关的错误

  • eval是内置的,所以覆盖它是不好的风格
  • 使用旧式类

像使用某种语言扩展一样使用 SymPy

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)

SymPy 小错误

var是用于创建Symbol对象的辅助函数,但它是为了在解释器中交互使用。不要在库代码中使用它,因为它会在命名空间中注入全局变量作为副作用。只需使用Symbol('x').

现在关于x+2可调用

在 0.7.2 中实现了递归调用。这意味着您可以创建一个Expr包含未评估的符号对象的 SymPy 树,并将整个树应用于另一个对象,调用向内传播,直到所有未评估的对象都被评估的对象替换。我想上面的描述不清楚,所以这里是一个例子:

您想创建一个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)中将再次引发错误。

于 2013-05-26T09:30:53.587 回答
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.20.7.1rc1版本失败。

于 2013-05-26T07:28:25.107 回答
1

这有几个问题。

  • 您没有将类定义为对象
  • 您将函数 eval 命名为保留字

尝试这个:

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

高温高压

于 2013-05-26T04:35:11.780 回答