while循环的常见故障:为什么?

时间:2016-05-24 09:38:18

标签: python loops while-loop

我经常发现自己处理类似于以下代码触发的故障的问题。正如你所看到的,我在这个例子中使用的反措施是徒劳的:由于某种原因,它看起来像while len(some_list) > n + 1最终给出了#34;误报"。

当然,我可以使用pass语句来覆盖这个"有趣的行为" (即使通过我认为它会有点" hacky"它会起作用)。但是,重点是:为什么会发生这种情况呢?

some_list = [2,3,2]

some_list.sort(reverse=True)

n = 0
while len(some_list) > 1 and n < len(some_list) - 1:
    try:
        while len(some_list) > n + 1:
            # This `if` statement was my last counter-measure
            if n + 1 >= len(some_list):
                break
            while some_list[n] == some_list[n+1]:
                some_list[n] += some_list.pop(n+1)
            else:
                n += 1
    except:
        print "WTF!!! len =",len(some_list),", n =",n
        raise

这是命令行的响应:

WTF!!! len = 2 , n = 1
  Traceback (most recent call last):
    File "example.py", line 11, in <module>
      while some_list[n] == some_list[n+1]:
IndexError: list index out of range

澄清:

  • 我故意使用.pop()故意消除该元素。
  • 问题的目的是确定造成这种错误的原因,别无其他。
  • 代码只是一个触发我想在问题中公开的异常的例子。
  • &#34;目的&#34;代码正在消除列表重复项,将它们添加到相邻元素(预期相同)。

错误的猜测

使用@Kevin M granger推荐的调试器后:

-> while len(some_list) > n + 1:
(Pdb) print len(some_list), ">", n + 1
3 > 2
(Pdb) next
> /tmp/kpasa.py(10)<module>()
-> if n + 1 >= len(some_list):
(Pdb) print n + 1, ">=", len(some_list)
2 >= 3
(Pdb) next
> /tmp/kpasa.py(13)<module>()
-> while some_list[n] == some_list[n+1]:
(Pdb) print len(some_list), n
3 1
(Pdb) next
> /tmp/kpasa.py(14)<module>()
-> some_list[n] += some_list.pop(n+1)
(Pdb) next
> /tmp/kpasa.py(13)<module>()
-> while some_list[n] == some_list[n+1]:
(Pdb) print len(some_list), n
2 1
(Pdb) next
IndexError: 'list index out of range'

我意识到自己的愚蠢。没有假阳性&#34;一点都不这个问题实际上是愚蠢的,所以我同意它必须被删除。

我很抱歉我的粗鲁和愚蠢。

3 个答案:

答案 0 :(得分:2)

while some_list[n] == some_list[n+1]:
    some_list[n] += some_list.pop(n+1)

pop这里减少了列表的长度,并且在下一次while次迭代时,不能保证len(some_list) > n + 1,因此可能发生异常。您可以将内部while更改为:

while len(some_list) > n + 1 and some_list[n] == some_list[n+1]:
    some_list[n] += some_list.pop(n+1)

答案 1 :(得分:1)

你的麻烦在这里:

while some_list[n] == some_list[n+1]:
    some_list[n] += some_list.pop(n+1)

当n = 1时,你弹出some_list的最后一项并将其添加到some_list [1]。 &#34; pop&#34;修改列表,所以现在some_list现在是[3,4]。然后你回到&#34;而#34;条件,你检查some_list [1] == some_list [2],但some_list不再有索引2的项目;你刚刚弹出它。

这里有一种不同的方法(至少在我看来)更清晰(尽管我猜测你想做什么:

some_list = [2,3,2]

some_list.sort(reverse=True)

new_list = []
prior_value = None
for old_value in some_list:
    if old_value == prior_value:
        new_list[-1] += old_value
    else:
        new_list.append(old_value)
        prior_value = old_value

print new_list

答案 2 :(得分:0)

some_list[n] += some_list.pop(n+1)行中,您可以减少列表的大小。当它下一次评估while some_list[n] == some_list[n+1]:时,some_list[n+1]会引发一个IndexError,因为该列表现在的长度小于n + 1个元素。