Python:用表达式替换函数,数学表达式为字符串,带Sympy?

Python:用表达式替换函数,数学表达式为字符串,带Sympy?,python,replace,sympy,symbolic-math,mathematical-expressions,Python,Replace,Sympy,Symbolic Math,Mathematical Expressions,我有一个函数定义,作为字符串,比如func_def=fx,y=x+2*y+3。 我有一个数学表达式,作为一个字符串,包括这个函数,比如 expr='2*a*b+fb+a,2*b' 在表达式中,如何用函数的值替换函数? 换句话说,如何获得字符串expr_eval=2*a*b+b+a+2*2*b+3 是否有一个简单的解决方案,例如使用sympify和subs以及其他一些函数的组合的Sympy?我觉得应该有一个,但找不到。我必须对许多包含许多符号的方程式进行此操作,因此分别为它们中的每一个创建Symp

我有一个函数定义,作为字符串,比如func_def=fx,y=x+2*y+3。 我有一个数学表达式,作为一个字符串,包括这个函数,比如 expr='2*a*b+fb+a,2*b'

在表达式中,如何用函数的值替换函数? 换句话说,如何获得字符串expr_eval=2*a*b+b+a+2*2*b+3

是否有一个简单的解决方案,例如使用sympify和subs以及其他一些函数的组合的Sympy?我觉得应该有一个,但找不到。我必须对许多包含许多符号的方程式进行此操作,因此分别为它们中的每一个创建Sympy符号似乎不是一个很好的选择

现在,我使用正则表达式,但我发现这个解决方案很复杂,用其他数量的变量来概括其他函数,缩放和读取。事情是这样的:

进口稀土 func_def=fx,y=x+2*y+3 expr='2*a*b+fb+a,2*b' 用函数提取子串 str_to_replace=re.findallr'f\[a-zA-z0-9\*\\+\']*,[a-zA-z0-9\*\\+\'/]*\',expr str_to_replace=str_to_replace[0] 提取子字符串中的函数名和参数 函数名,参数,\=re.split'\\\\',str\u to\u replace args=args.split',' args=[args中i的i.strip] 解析函数定义 func_def_lhs,func_def_rhs=函数定义拆分'=' func_def_name,args_def,\=re.split'\| \',func_def_lhs args_def=args_def.split',' args_def=[args_def中i的i.strip] 将定义中的每个参数替换为其表达式 对于i,枚举args_def中的arg_def: func_def_rhs=func_def_rhs.replacearg_def,{}.formatargs[i] expr_eval=expr.replacestr_to_replace,{}.formatfunc_def_rhs 您可以使用re.sub:

显示:

2*a*b + ((b+a) + 2*(2*b) + 3) + ((5) + (2*c) + (3+a) - 2)
2*a*b + a + b + 2*(2*b) + 3 + 5 + 2*c + a + 3 - 2
正则表达式,细分如下:

(                   begin capturing group for function
   .                match any character (function nname)
   \(               match open parenthesis
   (                begin capturing group for variable
     [^\)]+         match at least one non-parenthesis character
     ,?             match a comma if it's there
   )                end variable capturing 
   +?               match at least one variable
   \)               match close parenthesis
)                   end capturing group
如果您不介意简化输出,可以使用您提到的Symphy方法:

import sympy

expr = '2*a*b + f(b+a, 2*b) + g(5, 2*c, 3+a)'
f1 = "f(x, y) = x + 2*y + 3"
f2 = "g(x, y, z) = x + y + z - 2"

def split(fn):
    return str(fn).partition("(")

def check_fn(ex):
    name, sep, rest = split(ex)
    return name and sep

def parse_functions(functions):
    fns = {}
    for f in functions:
        name, _, rest = split(f)
        fn = rest.split(" = ")
        fns[name] = fn[0][:-1].split(", "), fn[1]
    return fns

def expand(expr, functions):
    fns = parse_functions(functions)

    def sub_fn(ex):
        with sympy.evaluate(False):
            vs, fn = fns[split(ex)[0]]
            fn = sympy.UnevaluatedExpr(sympy.sympify(fn))
            return fn.subs(dict(zip(vs, str(ex)[2:-1].split(", "))))

    return sympy.sympify(expr).replace(check_fn, sub_fn)

print(sympy.StrPrinter({'order':'none'})._print(expand(expr, [f1, f2])))
显示:

2*a*b + ((b+a) + 2*(2*b) + 3) + ((5) + (2*c) + (3+a) - 2)
2*a*b + a + b + 2*(2*b) + 3 + 5 + 2*c + a + 3 - 2

请注意,这假设您需要完整、未简化、无序的公式。

编辑以添加对多个公式的支持functions@presenter我对它进行了更新,添加了一个只使用sympy方法,而不使用正则表达式的方法。非常感谢!在第一种解决方案中,您能否详细说明模式。\[^\]+,?+?\?在第二个解决方案中,您需要sympy.abc import x,y,f中的行做什么?@presenter添加了解释!而且,sympy导入是不必要的,所以我删除了它们。它们来自于我以前尝试的一些方法。