即使我使用反向范围,仍然会发生“在Python中列表索引超出范围”的情况

2024-09-28 19:29:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我发现,当我在for循环中使用“pop”时,它可能会出现类似“列表索引超出Python范围”的错误。原因删除一个索引会使列表变短

并且还发现,如果我使用某种反向范围,我可以修正这个错误。 但当我试图应用我在堆栈溢出上学到的知识时,我仍然无法解决这个问题

比如说

candidates = []
def make_candidates(user_group, ban_group):
    for i in range(len(user_group)-1, -1, -1):   
        for j in range(len(ban_group)):
            if len(user_group[i]) == len(ban_group[j]):
                candidates.append(user_group.pop(i))

    return candidates

print(make_candidates(["frodo", "fradi", "crodo", "abc123", "frodoc"], ["*rodo", "*rodo", "******"]))  

范围是(4,-1,-1),所以“i”是4到0

当'i=4,j=2'时,len(user_gorup[4])==len(ban_group[2])->;候选人=[“frodoc”]->;用户组=[“弗罗多”、“弗雷迪”、“克罗多”、“abc123”]

当'i=3,j=2'时,len(用户组[3])==len(禁止组[2])->;候选人=[“frodoc”,“abc123”]->;用户组=[“弗罗多”、“弗雷迪”、“克罗多”]

这样,就没有列表外索引。当距离变短时,列表也变短,所以没有问题。不是吗?为什么还会发生错误


Tags: ingt列表formakelen错误group
1条回答
网友
1楼 · 发布于 2024-09-28 19:29:04

range没有什么魔力。它不与for语句交互-它只提供一系列要使用的数值

在外部循环for i in range(len(user_group)-1, -1, -1):中,在任何循环发生之前,range对象在时间之前创建一次。第一次通过,我们使用索引i == 4,然后使用i == 3,依此类推

您的期望是,即使列表被缩短,i仍然是列表的有效索引。但事实显然并非如此。仔细观察-有j很多机会删除内部循环中的项,因此在i减少之前,列表可以被.pop多次删除

但即便如此——假设只删除了一项——现在实际上是i您想要的索引?这样的逻辑是非常棘手的,没有理由做这样棘手的事情。根本没有理由使用索引-您应该直接引用列表元素,并且在完成之前不应该尝试删除任何内容

首先计算candidates,然后计算,如果需要,可以计算一个独立的非候选用户列表

我将通过使用函数为关键步骤命名来简化代码,然后通过使用列表理解而不是循环来进行处理-这使您不必考虑.append和过程逻辑,并且让您只描述所需的列表

def should_ban(user, ban_group):
    # I don't understand the reason for comparing name lengths, but
    # this should do the same as your original code tried to do:
    return any(len(user) == len(ban) for ban in ban_group)

def ban_candidates(user_group, ban_group):
    return [user for user in user_group if should_ban(user, ban_group)]

# Then we can filter the bans out of the user group:
def unbanned(user_group, banned):
    return [user for user in user_group if user not in banned]

相关问题 更多 >