如何不使用eval()从函数字典构建高级公式?
问题描述
我有两个函数字典,想用来构建更复杂的函数,目标是能通过字典键替换不同的函数。我知道用eval()在安全性和性能上都不是最优解,但实在想不出别的办法。
我写了一段有语法错误的代码:
import numpy as np def formula(x): p1 = 10 p2 = 20 p3 = 30 p4 = 40 p5 = 50 p6 = 60 basic = {0:'+', 1:'-', 2:'*', 3:'/'} advanced = {0:np.exp, 1:np.sin, 2:np.cos, 3:np.tan, 4:np.arcsin} f = advanced[0](x basic[1] p1) print(f)
我的目标是实现f = np.exp(x - p1),目前用下面的代码实现了功能,但依赖eval():
f = eval(f"{advanced[0].__name__}({x} {basic[1]} {p1})")
解决方案
不用eval()的核心是把运算符也封装成函数,而非字符串,这样就能直接通过函数调用组合运算,完全避开字符串解析的问题。
1. 重构运算符字典
借助Python内置的operator模块,把basic字典里的字符串运算符替换成对应的函数:
import numpy as np import operator def formula(x): p1 = 10 p2 = 20 p3 = 30 p4 = 40 p5 = 50 p6 = 60 # 用函数替代字符串运算符 basic = { 0: operator.add, # 对应 '+' 1: operator.sub, # 对应 '-' 2: operator.mul, # 对应 '*' 3: operator.truediv # 对应 '/' } advanced = {0:np.exp, 1:np.sin, 2:np.cos, 3:np.tan, 4:np.arcsin} # 先执行基础运算,再传入高级函数 intermediate = basic[1](x, p1) # 等价于 x - p1 f = advanced[0](intermediate) # 等价于 np.exp(x - p1) print(f)
2. 支持复杂嵌套组合
如果需要构建更复杂的表达式(比如np.sin(x * p2 + p3)),可以通过链式调用函数实现:
# 示例:构建 np.sin(x * p2 + p3) step1 = basic[2](x, p2) # x * p2 step2 = basic[0](step1, p3) # (x*p2) + p3 f = advanced[1](step2) # np.sin(step2)
方案优势
- 安全:不会执行任意字符串代码,彻底避免代码注入风险
- 高效:直接调用函数比
eval的字符串解析+执行快得多 - 易维护:逻辑清晰,调试和修改都更方便
内容的提问来源于stack exchange,提问作者Trippingbillies41
相关产品推荐
相关产品推荐

