如何实现禁用eval的单变量字符串表达式计算函数
问题描述
需求:实现一个单变量函数calculate_from_string,输入为包含+-*/数学运算的字符串表达式(如"5+3"),调用后需返回对应计算结果(如8)。本人尝试多种方法均未成功,且代码中禁止使用eval函数。相关代码定义如下:
def calculate_from_string(string): # 我试了很多方法都没成功,而且这段代码里不能用eval函数。
解决方案
基础版:处理二元运算
适用于仅包含两个操作数和一个运算符的简单表达式(如"5+3"、"12/4"):
def calculate_from_string(string): # 映射运算符到对应的计算逻辑 op_handlers = { '+': lambda a, b: a + b, '-': lambda a, b: a - b, '*': lambda a, b: a * b, '/': lambda a, b: a / b # 若需整数除法,替换为// } # 遍历运算符拆分表达式 for op in op_handlers: if op in string: num1_str, num2_str = string.split(op) try: # 转换为数值并去除可能的空格 num1 = float(num1_str.strip()) num2 = float(num2_str.strip()) return op_handlers[op](num1, num2) except ValueError: raise ValueError("输入表达式格式错误,请确保是合法的数字运算") # 处理单独数字的情况 try: return float(string.strip()) except ValueError: raise ValueError("输入表达式格式错误")
进阶版:支持多运算符与运算优先级
如果需要处理"3+4*2"、"10/2-3"这类包含运算优先级的复杂表达式,可通过**中缀转后缀表达式(逆波兰表达式)**实现:
def calculate_from_string(string): # 定义运算符优先级 op_precedence = {'+': 1, '-': 1, '*': 2, '/': 2} output_queue = [] op_stack = [] tokens = [] # 拆分表达式为数字和运算符的token列表 i = 0 str_len = len(string) while i < str_len: # 提取数字(支持小数) if string[i].isdigit() or string[i] == '.': j = i while j < str_len and (string[j].isdigit() or string[j] == '.'): j += 1 tokens.append(string[i:j]) i = j # 提取运算符 elif string[i] in '+-*/': tokens.append(string[i]) i += 1 # 跳过空格 elif string[i].isspace(): i += 1 else: raise ValueError(f"表达式包含无效字符:{string[i]}") # 中缀表达式转后缀表达式 for token in tokens: if token.replace('.', '', 1).isdigit(): output_queue.append(float(token)) else: # 弹出优先级不低于当前运算符的栈顶元素 while op_stack and op_precedence[op_stack[-1]] >= op_precedence[token]: output_queue.append(op_stack.pop()) op_stack.append(token) # 弹出剩余运算符 while op_stack: output_queue.append(op_stack.pop()) # 计算后缀表达式 calc_stack = [] for item in output_queue: if isinstance(item, float): calc_stack.append(item) else: b = calc_stack.pop() a = calc_stack.pop() if item == '+': calc_stack.append(a + b) elif item == '-': calc_stack.append(a - b) elif item == '*': calc_stack.append(a * b) elif item == '/': if b == 0: raise ZeroDivisionError("除数不能为0") calc_stack.append(a / b) if len(calc_stack) != 1: raise ValueError("输入表达式格式错误") return calc_stack[0]
使用示例
# 基础版测试 print(calculate_from_string("5+3")) # 输出 8.0 print(calculate_from_string("12/4")) # 输出 3.0 # 进阶版测试 print(calculate_from_string("3+4*2")) # 输出 11.0 print(calculate_from_string("10/2-3")) # 输出 2.0
内容的提问来源于stack exchange,提问作者Husam Marrid
相关产品推荐
相关产品推荐

