1 安装
可以使用 pip 安装:
pip install cexprtk
注意:安装需要安装兼容的 C++ 编译器。
2 用法
1)示例:计算一个简单的方程
计算算术表达式 (5+5) * 23
import cexprtk
cexprtk.evaluate_expression("(5+5) * 23", {}) # 230.0
2)示例:使用变量
通过将字典传递给 evaluate_expression 函数,可以在表达式中使用变量。这会将变量名称映射到其值。可以使用变量值重新计算上一示例中的表达式:
cexprtk.evaluate_expression("(A+B) * C", {"A" : 5, "B" : 5, "C" : 23}) # 230.0
3)示例:重用表达式
使用该 evaluate_expression() 函数时,数学表达式被解析、计算,然后立即丢弃。此示例演示如何重复使用 an Expression 进行多个计算。
- 将定义一个表达式来计算圆的周长,然后重新使用它来计算几个不同半径的值。
- 首先创建一个包含变量 r (半径)的 Symbol_Table ,它还可以添加常量,例如 π。
st = cexprtk.Symbol_Table({'r' : 1.0}, add_constants= True)
- 现在创建了一个实例 Expression ,定义函数:
circumference = cexprtk.Expression('2*pi*r', st)
- 初始 Symbol_Table r=1 ,只需调用表达式即可计算此半径:
circumference() # 6.283185307179586
- 现在,使用 Symbol_Table 的 属性 .variables 返回的类似字典的对象将半径更新为 3.0:
st.variables['r'] = 3.0
circumference() # 18.84955592153876
4)示例:定义自定义函数
Python 可以将具有Symbol_Table的函数进行注册,然后在 Expression 中使用。在此示例中,将定义一个自定义函数,该函数在给定范围内生成随机数。
import random
def rnd(low, high):
return random.uniform(low,high)
# 注册rnd 函数
st = cexprtk.Symbol_Table({})
st.functions["rand"] = rnd
Symbol_Table 的 functions 属性像字典一样被访问。在前面的代码片段中,将创建一个符号表,然后将 rnd 函数分配给 rand 键。此键在 cexprtk 表达式中用作函数的名称。键不能与现有变量、常量或保留函数名称相同。
该 rand 函数现在将在表达式中使用。此表达式选择一个介于 5 和 8 之间的随机数,然后将其乘以 10。后续代码片段显示了Expression的实例化,然后对其进行了几次评估。可能会从表达式中得到与所示不同的数字,这是因为随机数生成器将使用与示例中使用的不同种子进行初始化。
e = cexprtk.Expression("rand(5,8) * 10", st)
e() # 61.4668441077191
e() # 77.13523163246415
5)示例:定义未知符号解析器
可以通过 unknown_symbol_resolver_callback 参数将回调传递给 Expression 构造函数。在表达式解析期间,当遇到不在与 Symbol_Table 关联的变量或常量时,将调用此Expression回调 。
回调可以为导致注册新符号或标记错误条件提供一些逻辑。
以下示例显示了符号解析程序的潜在用途:
- 表达式包含 f_VARIABLENAME 和 m_VARIABLENAME 形式的变量
- 实际变量名称前加上前缀 m_ 或 f_ 在(可能表示性别)
- VARIABLENAME 应用于在字典中查找所需的值
- 应根据其前缀对 的 VARIABLENAME 字典值进行加权:m_ 变量应乘以 0.8, f_ 变量应乘以 1.1
方案:
- 首先定义 VARIABLENAME 字典:
variable_values = { 'county_a' : 82, 'county_b' : 76}
- 现在回调已定义。这需要一个参数 symbol,它给出了在表达式中找到的缺失变量的名称:
def callback(symbol):
# Tokenize the symbol name into prefix and VARIABLENAME components.
prefix,variablename = symbol.split("_", 1)
# Get the value for this VARIABLENAME from the variable_values dict
value = variable_values[variablename]
# Find the correct weight for the prefix
if prefix == 'm':
weight = 0.8
elif prefix == 'f':
weight = 1.1
else:
# Flag an error condition if prefix not found.
errormsg = "Unknown prefix "+ str(prefix)
return (False, cexprtk.USRSymbolType.VARIABLE, 0.0, errormsg)
# Apply the weight to the
value *= weight
# Indicate success and return value to cexprtk
return (True, cexprtk.USRSymbolType.VARIABLE, value, "")
- 剩下的就是向Expression 实例注册回调并计算表达式。要计算的表达式为:
st = cexprtk.Symbol_Table({})
# (0.8*82) - (1.1*76) = -18
e=cexprtk.Expression("(m_county_a - f_county_b)", st, callback)
e.value() # -18.0
6)示例:包含用于生成多个值的 return 语句的表达式
Exprtk 表达式可以返回多个值,这些结果可以通过该 results() 方法访问。
下面的示例显示了向包含数字的向量添加常量值的结果:
st = cexprtk.Symbol_Table({})
e = cexprtk.Expression("var v[3] := {1,2,3}; return [v+1];", st)
e.value() # nan
e.results() # [[2.0, 3.0, 4.0]]
注意,在调用 results() 该方法之前,必须计算表达式。
通过 results() 访问的值可以包含字符串、向量和实值的混合:
st = cexprtk.Symbol_Table({'c' : 3})
e = cexprtk.Expression("if(c>1){return ['bigger than one', c];} else { return ['not bigger than one',c];};",st)
e.value() # nan
e.results() # ['bigger than one', 3.0]
st.variables['c']=0.5
e.value() # nan
e.results() # ['not bigger than one', 0.5]
参考:https://github.com/mjdrushton/cexprtk