如何(轻松)获取可能由用户在运行时输入的"sin(x)*x^2"
字符串,并生成可以针对x
的任何值进行求值的Python函数?
答案 0 :(得分:48)
如果使用Python表示法,Python自己的内部编译器可以解析它。
如果你稍微改变符号,你会更开心。
import compiler
eq= "sin(x)*x**2"
ast= compiler.parse( eq )
您将获得一个可以使用的抽象语法树。
答案 1 :(得分:28)
您可以使用Python parser
:
import parser
formula = "sin(x)*x**2"
code = parser.expr(formula).compile()
from math import sin
x = 10
print eval(code)
它比纯eval
表现更好,当然也避免了代码注入!
答案 2 :(得分:14)
f = parser.parse('sin(x)*x^2').to_pyfunc()
可以使用PLY,pyparsing,内置标记器,解析器,ast来定义parser
。
请勿在用户输入上使用eval
。
答案 3 :(得分:7)
pyparsing可能会做你想要的(http://pyparsing.wikispaces.com/),特别是如果字符串来自不受信任的来源。
另请参阅http://pyparsing.wikispaces.com/file/view/fourFn.py,了解一个功能齐全的计算器。
答案 4 :(得分:2)
为了强调J.F.Sebastian的建议,“eval”甚至“编译器”解决方案都可以对微妙的安全漏洞开放。输入的可信度如何?使用'编译器',您至少可以过滤出来自AST的getattr查找等内容,但我发现使用PLY或pyparsing比使用Python帮助更容易实现这一点。
此外,'编译器'笨拙且难以使用。它已在3.0中弃用并删除。你应该使用'ast'模块(在2.6中添加,在2.5中可用作'_ast')。
答案 5 :(得分:1)
与vartec达成协议。我会使用SymPy - 特别是lambdify函数应该完全按照你想要的那样。
请参阅:http://showmedo.com/videotutorials/video?name=7200080&fromSeriesID=720
对此有一个非常好的解释。
祝福,
答案 6 :(得分:0)
Sage旨在作为matlab替换,并在intro videos中演示了与您的案例类似的处理方式。他们似乎支持广泛的方法。由于代码是开源的,您可以浏览并亲自了解作者如何处理此类案例。