我认为你需要改变一下你的方式。在
正在创建Var函数。
您确实希望示例中的Var是一个Function类。sympy是围绕函数是类而设计的,并使用eval()类方法来计算它们。重写Function子类的__call__似乎非常不标准,而且我还没有看到任何使用这个的sympy内置函数,所以我认为这不是正确的方法。一种方法是创建一个工厂函数来为您创建类:def Variation(path_, st_, en_, v_):
class Variation(Function):
nargs = 2
path = path_
st = st_
en = en_
ends = [st, en]
v = v_
@classmethod
def eval(cls, tt, ss):
if tt in cls.ends:
return cls.path(tt)
if ss == 0:
return cls.path(tt)
return cls.v(tt, ss)
return Variation
Var = Variation(c, a, b, Function(r'\vartheta'))我已经用一个实际的函数替换了您的'name'变量,这似乎更合理。在
现在,您可以使用标准标志创建变体并阻止立即求值(如果需要):
^{pr2}$
您也可以通过展平Var函数并将sten和{}参数直接传递到eval()中,这将删除工厂函数的额外层:class Variation(Function):
@classmethod
def eval(cls, path, st, en, v, tt, ss):
if tt in [st, en]:
return path(tt)
elif ss == 0:
return path(tt)
else:
return v(tt, ss)
Variation(c, a, b, Function(r'\vartheta'), a, t)
>>> Variation(c, a, b, \vartheta, a, t)
请注意,由于您可以重写.eval(),因此您可以对其进行修改,使其不会自动简化(如果需要),并且只返回一个cls的新实例:class Variation(Function):
no_eval = True
@classmethod
def eval(cls, tt, ss):
if cls.no_eval:
return cls(tt, ss, evaluate=False)
# etc.
自定义.subs()
默认情况下,无论何时执行subs(),sympy也将执行eval()(按照the ^{} docs)。因此,默认情况下,当您使用一个特殊值执行.subs()时,.eval()将被调用,函数将被简化。在
但是,如果需要,现在可以重写._eval_subs()并执行自己的操作:class Variation(Function):
...
def _eval_subs(self, old, new):
# return self to do no substitutions at all
return self
# return None to continue normally by next calling _subs on the arguments to this Function
# return some other Expression to return that instead.
请注意,._eval_subs()返回的任何内容随后也将被.eval()编辑。如果您想绕过这个问题,可以按照上面的说明覆盖.eval()。在
所以我认为这回答了关于如何修改.subs()行为的问题。。。在
我不太明白你想要什么:is there a good guide to construct arbitrary mathematical functions on python?
我认为sympy相当不错,它的代码库中有许多合理的文档和许多内置的示例,这些都很容易被剽窃。无论如何,请求向导是在stackoverflow上off-topic (see point 4);-)。在