我有一个字符串,它是一个数学方程式,但带有一些自定义函数。我需要找到所有这些函数并用一些代码替换它们。
例如我有一个字符串:
a+b+f1(f2(x,y),x)
我想要将 f2(x,y)
替换为 x+y^2
和 f1(x,y)
的代码code> 与 sin(x+y)
。
如果像示例中一样支持嵌套函数,那就太理想了。但是,如果不支持嵌套,它仍然有用。
据我从类似主题中了解到,这可以使用编译器模块(如 compiler.parse(eq)
)来完成。我如何使用 compiler.parse(eq)
创建的 AST 对象重建我的字符串,替换所有找到的函数?
我只需要执行替换,然后字符串就会在其他程序中使用。不需要评估。
最佳答案
这是一个最小的工作示例(+, - , *,/, **
二元和一元运算以及函数调用已实现)。操作的优先级用括号设置。
比给定示例的功能多一点:
from __future__ import print_function
import ast
def transform(eq,functions):
class EqVisitor(ast.NodeVisitor):
def visit_BinOp(self,node):
#generate("=>BinOp")
generate("(")
self.visit(node.left)
self.visit(node.op)
#generate("ici",str(node.op),node._fields,node._attributes)
#generate(dir(node.op))
self.visit(node.right)
generate(")")
#ast.NodeVisitor.generic_visit(self,node)
def visit_USub(self,node):
generate("-")
def visit_UAdd(self,node):
generate("+")
def visit_Sub(self,node):
generate("-")
def visit_Add(self,node):
generate("+")
def visit_Pow(self,node):
generate("**")
def visit_Mult(self,node):
generate("*")
def visit_Div(self,node):
generate("/")
def visit_Name(self,node):
generate(node.id)
def visit_Call(self,node):
debug("function",node.func.id)
if node.func.id in functions:
debug("defined function")
func_visit(functions[node.func.id],node.args)
return
debug("not defined function",node.func.id)
#generate(node._fields)
#generate("args")
generate(node.func.id)
generate("(")
sep = ""
for arg in node.args:
generate (sep)
self.visit(arg)
sep=","
generate(")")
def visit_Num(self,node):
generate(node.n)
def generic_visit(self, node):
debug ("\n",type(node).__name__)
debug (node._fields)
ast.NodeVisitor.generic_visit(self, node)
def func_visit(definition,concrete_args):
class FuncVisitor(EqVisitor):
def visit_arguments(self,node):
#generate("visit arguments")
#generate(node._fields)
self.arguments={}
for concrete_arg,formal_arg in zip(concrete_args,node.args):
#generate(formal_arg._fields)
self.arguments[formal_arg.id]=concrete_arg
debug(self.arguments)
def visit_Name(self,node):
debug("visit Name",node.id)
if node.id in self.arguments:
eqV.visit(self.arguments[node.id])
else:
generate(node.id)
funcV=FuncVisitor()
funcV.visit(ast.parse(definition))
eqV=EqVisitor()
result = []
def generate(s):
#following line maybe usefull for debug
debug(str(s))
result.append(str(s))
eqV.visit(ast.parse(eq,mode="eval"))
return "".join(result)
def debug(*args,**kwargs):
#print(*args,**kwargs)
pass
用法:
functions= {
"f1":"def f1(x,y):return x+y**2",
"f2":"def f2(x,y):return sin(x+y)",
}
eq="-(a+b)+f1(f2(+x,y),z)*4/365.12-h"
print(transform(eq,functions))
结果
((-(a+b)+(((sin((+x+y))+(z**2))*4)/365.12))-h)
警告
该代码适用于 Python 2.7,并且由于它依赖于 AST,因此不能保证适用于其他版本的 Python。 Python 3 版本不工作。
关于python - 在 Python 中使用自定义函数解析方程式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27960965/