Python后缀表达式求值未用除法却触发ZeroDivisionError问题排查
后缀表达式求值程序的ZeroDivisionError问题分析与解决
问题重现
以下是Python后缀表达式求值的代码:
from collections import deque def postfixExpression(expression: str) -> int: if not expression: return -1 expression_list = expression.split(" ") stack = deque() for ex in expression_list: print(ex, stack) try: stack.append(int(ex)) except ValueError: b = stack.pop() a = stack.pop() switcher = { "+" : a + b, "-" : a - b, "*" : a * b, "/" : int(a / b), "^" : a ** b, } if ex not in switcher.keys(): raise ValueError(f"Wrong expression-> {ex}") else: stack.append(switcher.get(ex)) return stack.pop() expression = "2 3 7 - 7 + 9 7 2 + - * *" print(f"\nResult {postfixExpression(expression)}")
该程序多数场景运行正常,但输入表达式"2 3 7 - 7 + 9 7 2 + - * *"时,未使用除法操作却抛出ZeroDivisionError。注释掉switcher字典中的"/" : int(a / b),行后,程序能得到预期结果0。
错误日志如下:
$ python temp/temp.py 4 deque([]) 6 deque([4]) * deque([4, 6]) 2 deque([24]) 1 deque([24, 2]) - deque([24, 2, 1]) + deque([24, 1]) 7 deque([25]) 7 deque([25, 7]) + deque([25, 7, 7]) 7 deque([25, 14]) 6 deque([25, 14, 7]) + deque([25, 14, 7, 6]) * deque([25, 14, 13]) * deque([25, 182]) 3 deque([4550]) 7 deque([4550, 3]) - deque([4550, 3, 7]) 7 deque([4550, -4]) + deque([4550, -4, 7]) 9 deque([4550, 3]) 7 deque([4550, 3, 9]) 2 deque([4550, 3, 9, 7]) + deque([4550, 3, 9, 7, 2]) - deque([4550, 3, 9, 9]) * deque([4550, 3, 0]) Traceback (most recent call last): 文件 "C:\Users\...\temp.py", 第11行, 位于 postfixExpression stack.append(int(ex)) ValueError: invalid literal for int() with base 10: '*' 在处理上述异常期间,又发生了另一个异常: Traceback (most recent call last): 文件 "C:\Users\...\temp.py", 第52行, 位于 main print(f"\nresult {postfixExpression(expression)}") 文件 "C:\Users\...\temp.py", 第19行, 位于 postfixExpression "/" : int(a / b), ZeroDivisionError: division by zero
核心错误原因
Python字典在初始化时会立即计算所有键值对的value表达式,而非按需计算。
当程序处理到表达式中的*运算符时,栈内元素为deque([4550, 3, 0]),此时弹出b=0、a=3。尽管当前要执行的是乘法,但创建switcher字典时,所有运算符对应的计算式都会被执行——包括除法的int(a / b),也就是int(3 / 0),直接触发除零错误。
解决方法
修改运算符处理逻辑,让计算操作仅在需要时才执行,常见方案有两种:
方案1:使用lambda函数延迟计算
将字典的值改为lambda函数,调用时再传入参数执行计算:
from collections import deque def postfixExpression(expression: str) -> int: if not expression: return -1 expression_list = expression.split(" ") stack = deque() # 定义运算符对应的lambda函数 ops = { "+": lambda a, b: a + b, "-": lambda a, b: a - b, "*": lambda a, b: a * b, "/": lambda a, b: int(a / b), "^": lambda a, b: a ** b, } for ex in expression_list: try: stack.append(int(ex)) except ValueError: if ex not in ops: raise ValueError(f"Wrong expression-> {ex}") b = stack.pop() a = stack.pop() # 仅在需要时执行对应运算 stack.append(ops[ex](a, b)) return stack.pop() expression = "2 3 7 - 7 + 9 7 2 + - * *" print(f"\nResult {postfixExpression(expression)}")
方案2:使用if-elif分支判断
放弃字典映射,改用条件分支直接处理运算符:
from collections import deque def postfixExpression(expression: str) -> int: if not expression: return -1 expression_list = expression.split(" ") stack = deque() for ex in expression_list: try: stack.append(int(ex)) except ValueError: b = stack.pop() a = stack.pop() if ex == "+": res = a + b elif ex == "-": res = a - b elif ex == "*": res = a * b elif ex == "/": res = int(a / b) elif ex == "^": res = a ** b else: raise ValueError(f"Wrong expression-> {ex}") stack.append(res) return stack.pop() expression = "2 3 7 - 7 + 9 7 2 + - * *" print(f"\nResult {postfixExpression(expression)}")
两种方案都能避免不必要的计算,只有当运算符是/时才会执行除法逻辑,从而解决无除法场景下的除零错误。
内容的提问来源于stack exchange,提问作者Saketh
相关产品推荐
相关产品推荐

