版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。
我想在python的函数参数中传递一个公式,其中公式是其他函数参数的组合。原则上,这看起来是这样的:
myfunction(x=2,y=2,z=1,formula="x+2*y/z")
6
或更一般:
def myformula(x,y,z,formula):
return formula(x,y,z)
这将允许用户根据x、y和z选择任何算术表达式,而无需创建新函数。
我预见到的一种可能性是在函数内转换代码行中的字符串。在python中有类似的可能吗?或者其他想法?谢谢
听起来像是EDOCX1的工作。不管怎样,主题上都有许多线程。
在python中,将带有参数的函数传递给另一个函数是否可能重复?
@没有,那不是复制品
我用一个lambda代替。Eval太危险了
感谢所有这些不同的解决方案。@乌布图,这个问题被纠正了。
使用sympy,可以计算数学表达式:
import sympy as sy
def myformula(formula, **kwargs):
expr = sy.sympify(formula)
return expr.evalf(subs=kwargs)
print(myformula(x=2,y=2,z=1,formula="x+2*y/z"))
# 6.00000000000000
print(myformula(x=2,y=2,z=1,formula="sin(x+y-z)"))
# 0.141120008059867
但是请注意,sympy.sympify确实使用eval这使得它不安全地应用于任意用户输入。因为可以组成字符串来欺骗eval执行任意的python代码。
一个更安全的选择是构建一个解析器来解析严格限制的数学表达式。下面是几个例子
使用ast分析表达式
使用Paul McGuire的Pyparsing
建议采用return expr.subs(kwargs)。
可评价print(myformula(x=2,y=2,z=1,formula="x+2*y/z>0"))。
@阿扎特:不幸的是,这改变了第二个例子的行为。
@UNUTBU也在寻找对此的答案,并决定查看文档以获取更多信息。我注意到,医生说sympify使用"eval",因此应该受到同样的审查…或者我可能遗漏了一些东西,因为我是一个初学者:docs.sympy.org/latest/modules/core.html
另外,如果您仍然处于活动状态,那么如果"我的公式"包含一些与您要传递的算术表达式不直接相关的附加参数,该怎么办?当我用一个星号而不是两个星号时是这样吗?
@罗克斯沃夫斯:谢谢你指出这一点。我完全错了。(虽然sympy使用ast解析引擎盖下的表达式,但我没有意识到它仍然依赖于调用eval)。下面是相关的Github问题,它可以帮助那些有兴趣跟踪(或促成)Sympy在这个问题上的进展的人。
我已经编辑了这篇文章来建议一些安全的解析方法,但不幸的是,它们在将字符串解析为可计算的数学表达式方面的能力还不够全面。
您的"myformula"与常规lambda表达式没有太大的不同,只是增加了将字符串解析为可执行python的负担。
(lambda x,y,z: x + 2*y/z)(5, 2, 10)
因此,您可以简单地将myFormula定义为
def myFormula(*args, formula):
formula(*args)
并称之为
myFormula(5, 2, 10, lambda x, y, z: x + 2*y/z)
您可以尝试使用lambda函数。像这样的东西可能适合你:
def myFormula(x,y,z):
return lambda x,y,z: x+2*y/z
这样就不必定义新函数,也不必将任何额外的东西作为参数传递。
关于lambda函数的额外信息:http://www.diveintopython.net/power_of_introspection/lambda_functions.html
http://pythonquerstheuniverse.wordpress.com/2011/08/29/lambda_教程/
https://docs.python.org/2/reference/expressions.html lambda
传递给myFormula的参数x、y和z被忽略;返回的函数只是一个接受3个参数的函数。