python - 在 Python 中使用自定义函数解析方程式

标签 python python-2.7 parsing equation

我有一个字符串,它是一个数学方程式,但带有一些自定义函数。我需要找到所有这些函数并用一些代码替换它们。

例如我有一个字符串:

a+b+f1(f2(x,y),x)

我想要将 f2(x,y) 替换为 x+y^2f1(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/

相关文章:

Python//解析Json到MySQL

parsing - 将 bufio.Scanner 的阅读器包装在 bufio.Reader 中有什么好处吗?

python - Keras Sequential 模型中使用的验证数据是什么?

python - PyCharm 导入 MySQL

python - 使用 pandas 进行插值时如何控制 X 和 Y

python - Python3中方法has_key的替换

java - 从 html 文档中解析 href 并通过 xpath 求值返回空指针异常

Python/pyspark 数据框重新排列列

python - 无法创建能够满足特定条件的 xpath

jquery - 有什么方法可以使用jinja2和flask形式而不是ajax和jquery或两者都使用?