执行Python代码得目标结果却触发KeyError: 'po5'求助
分析与修复你的Python表达式计算代码
首先,你的代码能得到预期结果但触发KeyError: 'po5',核心问题出在字典引用传递+循环中修改字典结构+递归逻辑的冗余执行这几个点上,咱们一步步拆解:
问题根源
字典是引用类型,递归修改了原对象
你写的car1=car只是把变量指向同一个字典对象,递归里修改car1的时候,外层的car也被同步修改了。当递归返回后,外层的for循环还在继续遍历原来的键列表,这时候有些键已经被pop删除了,自然就触发KeyError。循环中修改字典长度,导致遍历异常
for inter in range(len(car))是基于循环开始时的字典长度生成的序列,但循环体内执行了pop操作,字典长度变短了,后续的索引访问就会指向不存在的键(比如vocar[inter+1]可能已经被删除)。递归后没有终止当前循环
每次处理完一个运算符(+或-)并进入递归后,当前的for循环并没有终止,还会继续往后执行,尝试访问已经被删除的键,这也是报错的原因之一。
修复后的代码
下面是调整后的版本,解决了上述问题:
import copy car = {"po1": 50, "po2": "-", "po3": 15, "po4": "+", "po5": 12} def cal(car): # 每次递归都操作字典的深拷贝,避免修改原对象 current_car = copy.deepcopy(car) vocar = list(current_car.keys()) for inter in range(len(vocar)): val = current_car.get(vocar[inter]) if val == "+" or val == "-": # 获取左右操作数 left_key = vocar[inter-1] right_key = vocar[inter+1] left_val = current_car[left_key] right_val = current_car[right_key] # 计算新值 if val == "+": new_val = left_val + right_val else: new_val = left_val - right_val # 构建新的字典:移除运算符和右操作数,更新左操作数 new_car = {} for k in current_car: if k == left_key: new_car[k] = new_val elif k not in [vocar[inter], right_key]: new_car[k] = current_car[k] # 如果只剩一个键,返回结果;否则继续递归 if len(new_car) == 1: return new_car else: return cal(new_car) return current_car # 执行并打印结果 result = cal(car) print(result)
关键修改说明
- 使用深拷贝:每次递归都创建一个新的字典副本,避免递归修改影响外层的字典状态。
- 避免循环中修改原字典:直接构建新的字典来存储运算后的状态,而不是在原字典上做
pop和update操作,从根源上避免键不存在的问题。 - 递归后立即返回:处理完一个运算符并生成新字典后,直接进入递归并返回结果,终止当前循环,避免后续无效的键访问。
- 明确终止条件:当字典只剩一个键时,直接返回该结果,结束递归链。
运行这段代码会输出{'po1': 47},且不会触发任何KeyError。
内容的提问来源于stack exchange,提问作者Diyor Jaloldinov
相关产品推荐
相关产品推荐

