You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python递归遍历字典出现IndexError: list index out of range问题求助

递归遍历字典时的IndexError错误分析与解决

问题描述

你编写了一段遍历字典并判断值是否存在于字典键中的Python代码,执行时在if king_attack_moves[current][i] in king_attack_keys:处抛出IndexError: list index out of range错误。具体表现为处理{(450, 750): [(750, 450)]}时,变量i变为1,但该列表仅包含索引0的元素,你困惑于i为何会变成1。使用环境为Python 3.10.5和PyCharm 2020。

原代码

king_attack_moves = {(450, 750): [(750, 450)], (150, 450): [(450, 750)], (550, 50): [(150, 450), (50, 550)]}
king_attack_keys = [(450, 750), (150, 450), (550, 50)]

def standartization_for_king(current, king_keys, king_moves):
    if current in king_keys:
        for i in range(len(king_moves[current])):
            print(current,i,len(king_moves[current]))
            if king_moves[current][i] in king_attack_keys:
                current, king_moves = standartization_for_king(king_moves[current][i], king_keys,king_moves)
    return current, king_moves

current, king_attack_moves = standartization_for_king((550, 50), king_attack_keys, king_attack_moves)

错误原因

核心问题是递归过程中修改了循环依赖的current变量,导致后续循环迭代使用错误的current值,具体执行流程如下:

  1. 初始调用时current=(550,50),king_moves[current]的长度为2,因此循环i会取0和1。
  2. 当i=0时,king_moves[current][i]=(150,450)在king_attack_keys中,触发递归调用。
  3. 递归层层深入后,最终返回时current被修改为(450,750)。
  4. 回到初始循环的i=1迭代时,current已经是(450,750),而king_moves[(450,750)]的长度仅为1,i=1超出了列表的索引范围,因此抛出IndexError。

简单来说,循环的range是基于初始current的长度生成的,但中途current被修改,后续迭代用新的current去匹配旧的索引范围,自然会越界。

解决方案

不要在循环迭代过程中修改current变量,改用临时变量处理递归结果,或者提前固定要遍历的列表内容,避免current变化影响遍历逻辑。

方案1:遍历列表元素而非索引,避免修改循环依赖的current

king_attack_moves = {(450, 750): [(750, 450)], (150, 450): [(450, 750)], (550, 50): [(150, 450), (50, 550)]}
king_attack_keys = [(450, 750), (150, 450), (550, 50)]

def standartization_for_king(current, king_keys, king_moves):
    if current in king_keys:
        # 直接遍历当前current对应的移动列表,不修改current本身
        for move in king_moves[current]:
            print(current, move, len(king_moves[current]))
            if move in king_attack_keys:
                # 用临时变量接收递归返回结果,不覆盖原current
                _, king_moves = standartization_for_king(move, king_keys, king_moves)
    return current, king_moves

current, king_attack_moves = standartization_for_king((550, 50), king_attack_keys, king_attack_moves)

方案2:提前固定遍历的列表,避免current修改影响遍历

如果需要保留索引遍历的逻辑,可以提前复制当前current对应的列表,确保遍历过程不受current变化影响:

king_attack_moves = {(450, 750): [(750, 450)], (150, 450): [(450, 750)], (550, 50): [(150, 450), (50, 550)]}
king_attack_keys = [(450, 750), (150, 450), (550, 50)]

def standartization_for_king(current, king_keys, king_moves):
    if current in king_keys:
        # 提前复制当前current对应的移动列表,固定遍历内容
        current_moves = king_moves[current].copy()
        for i in range(len(current_moves)):
            print(current, i, len(current_moves))
            if current_moves[i] in king_attack_keys:
                # 用临时变量接收递归返回的current,不覆盖原循环依赖的current
                temp_current, king_moves = standartization_for_king(current_moves[i], king_keys, king_moves)
                # 若业务需要更新current,可在此处根据逻辑调整,但不会影响当前循环
    return current, king_moves

current, king_attack_moves = standartization_for_king((550, 50), king_attack_keys, king_attack_moves)

内容的提问来源于stack exchange,提问作者HaterOfCaptcha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 08:39:46