Python自定义数学求值器开发需求及问题修复
私人Python数学求值器优化方案
针对需求,以下是优化后的完整实现,解决了多列表运算、多函数组合及隐式乘法的问题,同时满足所有核心功能要求:
完整代码实现
import re import math class MathList(list): def __init__(self, iterable=()): super().__init__(iterable) def _op(self, other, op): """通用运算处理函数,实现笛卡尔积运算与标量运算""" result = [] # 处理两个列表的笛卡尔积运算 if isinstance(other, MathList): for x in self: for y in other: result.append(op(x, y)) # 处理列表与标量的运算 else: for x in self: result.append(op(x, other)) # 去重并保持元素首次出现的顺序 return MathList(dict.fromkeys(result).keys()) # 重载基础运算符 def __add__(self, other): return self._op(other, lambda a, b: a + b) def __sub__(self, other): return self._op(other, lambda a, b: a - b) def __mul__(self, other): return self._op(other, lambda a, b: a * b) def __truediv__(self, other): return self._op(other, lambda a, b: a / b) # 重载反向运算符,处理标量在前、列表在后的情况(如3 - [1,2]) def __radd__(self, other): return self._op(other, lambda a, b: b + a) def __rsub__(self, other): return self._op(other, lambda a, b: b - a) def __rmul__(self, other): return self._op(other, lambda a, b: b * a) def __rtruediv__(self, other): return self._op(other, lambda a, b: b / a) def preprocess_expression(expr): """预处理表达式,自动插入隐式乘法的乘号""" # 正则规则覆盖所有隐式乘法场景 patterns = [ # 数字后接括号/列表:如2(3) → 2*(3);2[1,2] →2*[1,2] r'(\d+(?:\.\d+)?)\s*([\(\[])', # 括号/列表后接数字/括号/列表:如(3)2→(3)*2;[1,2](3)→[1,2]*(3) r'([\)\]])\s*(\d+(?:\.\d+)?|[\(\[])', # 括号与列表互相嵌套:如([1,2])→([1,2]);[(3)]→[(3)] r'(\()\s*(\[)', r'(\[)\s*(\()' ] for pattern in patterns: expr = re.sub(pattern, r'\1*\2', expr) return expr def custom_random(start, end, step=0.1): """自定义random函数,支持浮点数范围的序列生成""" result = [] current = start # 用round避免浮点数精度误差导致的循环异常 while round(current, 10) < round(end, 10): result.append(current) current += step current = round(current, 10) return MathList(result) def evaluate_math(expr): """主求值函数,处理所有输入表达式""" # 预处理隐式乘法 processed_expr = preprocess_expression(expr) # 替换普通列表为自定义MathList,实现重载运算 processed_expr = re.sub(r'\[(.*?)\]', r'MathList([\1])', processed_expr) # 构建安全的命名空间(仅包含允许的函数与常量) namespace = { '__builtins__': None, 'random': custom_random, 'MathList': MathList } # 导入math模块的所有公开函数与常量 for attr in dir(math): if not attr.startswith('_'): namespace[attr] = getattr(math, attr) try: result = eval(processed_expr, namespace) # 标量结果转换为单元素列表 if not isinstance(result, MathList): result = MathList([result]) return list(result) except Exception as e: raise ValueError(f"表达式解析错误: {expr}") from e # 测试用例 if __name__ == "__main__": print(evaluate_math("3")) # 输出: [3] print(evaluate_math("round(419.9)")) # 输出: [420] print(evaluate_math("[2,1]-[0,1]")) # 输出: [2, 1, 0] print(evaluate_math("random(0.1,0.5)")) # 输出: [0.1, 0.2, 0.3, 0.4] print(evaluate_math("log(e)")) # 输出: [1.0] print(evaluate_math("2(3)")) # 输出: [6] print(evaluate_math("(2+3)(4)")) # 输出: [20] print(evaluate_math("2[1,3]")) # 输出: [2, 6] print(evaluate_math("[1,2]*3")) # 输出: [3, 6] print(evaluate_math("random(1,5,2)")) # 输出: [1, 3]
核心功能实现说明
1. 隐式乘法支持
通过preprocess_expression函数使用正则表达式自动识别并插入乘号,覆盖所有常见隐式场景:
- 数字后接括号/列表(如
2(3)→2*(3)) - 括号/列表后接数字/括号/列表(如
[1,2]3→[1,2]*3) - 括号与列表互相嵌套(如
([1,2])→([1,2]))
2. 列表递归运算
通过自定义MathList类重载运算符,实现:
- 两个列表间的笛卡尔积运算(如
[2,1]-[0,1]生成所有元素对的减法结果) - 列表与标量的逐元素运算(如
[1,2]*3生成[3,6]) - 自动去重并保持元素首次出现的顺序
3. 自定义random函数
实现支持浮点数范围的序列生成,通过round处理浮点数精度问题,避免循环异常,默认步长为0.1,支持自定义步长。
4. Math模块集成
将math模块的所有公开函数与常量导入命名空间,支持如log(e)、sin(pi/2)等表达式求值。
5. 基础求值兼容
所有标量表达式求值后自动转换为单元素列表,保持输出格式统一;同时兼容Python内置函数(如round)的正常使用。
内容的提问来源于stack exchange,提问作者Machinexa
相关产品推荐
相关产品推荐

