在python中将公式作为函数参数传递

Pass a formula as a function parameter in python

我想在python的函数参数中传递一个公式,其中公式是其他函数参数的组合。原则上,这看起来是这样的:

1
2
myfunction(x=2,y=2,z=1,formula="x+2*y/z")
6

或更一般:

1
2
def myformula(x,y,z,formula):
   return formula(x,y,z)

这将允许用户根据x、y和z选择任何算术表达式,而无需创建新函数。

我预见到的一种可能性是在函数内转换代码行中的字符串。在python中有类似的可能吗?或者其他想法?谢谢


使用sympy,可以计算数学表达式:

1
2
3
4
5
6
7
8
9
10
11
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


您的"myformula"与常规lambda表达式没有太大的不同,只是增加了将字符串解析为可执行python的负担。

1
(lambda x,y,z: x + 2*y/z)(5, 2, 10)

因此,您可以简单地将myFormula定义为

1
2
def myFormula(*args, formula):
    formula(*args)

并称之为

1
myFormula(5, 2, 10, lambda x, y, z: x + 2*y/z)


您可以尝试使用lambda函数。像这样的东西可能适合你:

1
2
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