开发Telegram Bot函数绘图功能时如何计算带定义域的函数值
你不需要自行编写字符串解析器,用现有成熟库即可解决定义域处理问题,具体方案如下:
- 首选
numpy库处理数值计算,其内置的所有数学函数(包括sqrt、log、三角函数等)均支持广播运算,遇到超出定义域的输入时不会抛出异常,只会返回NaN(非数值),后续绘图时主流绘图库(如matplotlib)会自动跳过NaN对应的坐标点,刚好符合函数绘图的需求。 - 不要直接使用原生
eval执行用户输入的表达式,存在极高的代码注入风险,可通过ast模块做白名单校验,仅允许执行数学运算和指定的合法函数调用,示例实现如下:
import numpy as np import ast # 合法标识符白名单,可按需扩展支持更多数学函数 SAFE_WHITELIST = { 'x': None, 'sqrt': np.sqrt, 'log': np.log, 'log10': np.log10, 'sin': np.sin, 'cos': np.cos, 'tan': np.tan, 'abs': np.abs, 'exp': np.exp, 'pi': np.pi, 'e': np.e } def safe_calculate(expr: str, x_values: np.ndarray): # 解析抽象语法树校验合法性 parsed_expr = ast.parse(expr, mode='eval') for node in ast.walk(parsed_expr): # 校验变量、函数名均在白名单内 if isinstance(node, ast.Name): if node.id not in SAFE_WHITELIST: raise ValueError(f"不支持的标识符:{node.id}") elif isinstance(node, ast.Call): if not isinstance(node.func, ast.Name) or node.func.id not in SAFE_WHITELIST: raise ValueError(f"不支持的函数调用") # 安全执行表达式 return eval(compile(parsed_expr, '', 'eval'), SAFE_WHITELIST, {'x': x_values})
- 实际计算流程示例:
# 从用户输入获取x轴范围,比如-10到10,生成1000个连续采样点(比整数range绘图更平滑) x = np.linspace(-10, 10, 1000) # 用户输入y=sqrt(x),截取后得到表达式 func_expr = 'sqrt(x)' # 计算y值,x<0的位置会自动返回NaN y = safe_calculate(func_expr, x) # 后续直接传入x和y到绘图库即可自动得到合法区间的函数图像
如果需要提前获取函数的精确定义域给用户提示,可以额外引入sympy库做符号运算求解自然定义域,普通绘图场景下直接用上述numpy+ast的方案就足够满足需求。
内容的提问来源于stack exchange,提问作者Daniil Ivanov
相关产品推荐
相关产品推荐

