【问题标题】:Python: List index out of range inside while/for loopPython:在while / for循环内列出索引超出范围
【发布时间】:2018-01-02 12:45:25
【问题描述】:

我想制作一个 Tribonacci 序列。 (每个新项目都是该列表中前三个项目的总和。)但是每当我使用 while/for 循环时,它都会显示列表索引超出范围错误。谁能弄清楚这段代码有什么问题?

def tribonacci(signature, n):
    count = 0
    newlist = []
    while (len(newlist)<=n):
        newitem = signature[count]+signature[count+1]+signature[count+2]
        newlist.append(newitem)
        count = count+1
    print signature + newlist
tribonacci([1,1,1], 5)

在上面的代码中,我的预期输出是 [1,1,1,3,5,9,17,31]

Traceback (most recent call last):
File "C:\Users\Vasanth\Desktop\sample.py", line 9, in <module>
tribonacci([1,1,1], 5)
File "C:\Users\Vasanth\Desktop\sample.py", line 5, in tribonacci
newitem = signature[count]+signature[count+1]+signature[count+2]
IndexError: list index out of range

【问题讨论】:

  • 您没有发布回溯,所以这是推测性的,但我敢打赌 signature 在您开始时包含少于三个项目。
  • 您更新了计数,但您从未真正将项目附加到 signature,您使用它来计算 newitem,尽管这可能不是您的本意。
  • 你使用 count 的方式会导致失败。一旦计数为 4 或更高,您将超出签名范围...您必须以另一种方式处理它 ///
  • 如果您正在编写新代码,您绝对应该认真考虑以 Python 3 为目标。Python 2 的生命周期结束被推迟,但最初的 EOL 日期距离现在。
  • @A.Joly 只要count 大于零,错误实际上就会发生。

标签: python list concatenation indexoutofrangeexception


【解决方案1】:

在第一次迭代之后,您将 count 增加到 1,但没有以任何方式更新 signature。它包含 3 个项目,因此count + 2 将尝试索引列表超出其边界。

相反,您可以将添加新结果的列表的最后 3 项相加:

In [20]: def tribonacci(signature, n):
    ...:     result = list(signature)
    ...:     for _ in range(n):
    ...:         result.append(sum(result[-3:]))
    ...:     return result

或者,如果使用 Python 3 并希望创建一个生成器:

In [34]: from collections import deque
    ...: 
    ...: def tribonacci(signature, n):
    ...:     state = deque(signature, maxlen=3)
    ...:     yield from state
    ...:     
    ...:     for _ in range(n):
    ...:         next_value = sum(state)
    ...:         yield next_value
    ...:         state.append(next_value)
    ...: 

In [35]: tribonacci([1,1,1], 5)
Out[35]: <generator object tribonacci at 0x7f6ae11ef990>

In [36]: list(_)
Out[36]: [1, 1, 1, 3, 5, 9, 17, 31]

【讨论】:

  • 很好,虽然我可能会做result = list(signature) 所以signature 可能是一个元组。 deque 版本是一个非常好的主意。
【解决方案2】:

让我们将其简化为 MCVE:

signature = [1, 1, 1]
count = 0
while True:
    newitem = signature[count] + signature[count+1] + signature[count+2]
    count = count+1

在第一次迭代中,count0,因此“问题”行将有效地是:

    newitem = signature[0] + signature[1] + signature[2]

因为signature 是一个包含 3 项的列表,所以没关系。现在在第二次迭代中,count1,所以这一行将有效地变为:

    newitem = signature[1] + signature[2] + signature[3]

由于 signature 仅包含 3 个项目,因此没有 signature[3] 对象 - 您的索引超出范围。

【讨论】:

    【解决方案3】:

    简单的解决方案

    def tri(original_sig, n):
        sig = original_sig.copy()
        for i in range(n):
            sig.append(sum(sig[i:i+3]))
        return sig
    

    在您的代码中,您将新值附加到newlist,而不是signature。因此,在第一次迭代之后,您的代码将尝试访问超出 ist 大小的元素 3

    【讨论】:

      【解决方案4】:

      对原始代码的小修改效果很好:

      def tribonacci(signature, n):
          count = 0
          newlist = signature             # change here..
          while (len(newlist)<=(n+3)):    # here..
              newitem = signature[count]+signature[count+1]+signature[count+2]
              newlist.append(newitem)
              count = count+1
          print(newlist)                  # and here.
      

      测试:

      tribonacci([1,1,1], 5)
      tribonacci([2,2,2], 5)
      

      输出:

      [1, 1, 1, 3, 5, 9, 17, 31, 57]
      [2, 2, 2, 6, 10, 18, 34, 62, 114]
      

      编辑:如cmets中所说,这里会修改原来发送的列表。

      如果要保留原始列表:

      def tribonacci(signature, n):
          count = 0
          newlist = signature.copy()      # get a copy of original list
          while (len(newlist)<=(n+3)):    
              newitem = newlist[count]+newlist[count+1]+newlist[count+2] # use newlist rather than signature
              newlist.append(newitem)
              count = count+1
          print(newlist)
      

      测试:

      a = [1,1,1]
      tribonacci(a, 5)
      print(a)
      
      b = [2,2,2]
      tribonacci(b, 5)
      print(b)
      

      输出:

      [1, 1, 1, 3, 5, 9, 17, 31, 57]
      [1, 1, 1]
      [2, 2, 2, 6, 10, 18, 34, 62, 114]
      [2, 2, 2]
      

      【讨论】:

      • 最好提一下newlist = signature 实际上并没有创建新列表。
      【解决方案5】:
      def tribonacci(signature, n):
          count = 0
          newlist = []
          while (len(newlist)<=n):
              newitem = signature[count]+signature[count+1]+signature[count+2]
              newlist.append(newitem)
              count = count+1
              signature.append(newitem)
          print signature
      tribonacci([1,1,1], 5)
      

      您每次都在增加计数器的值,但您将新值附加到签名列表中。 所以签名的长度仍然只有 3 当代码试图获取签名列表的第 4 个元素时,它抛出了这个错误。

      【讨论】:

        【解决方案6】:
        item = [1,1,1]
        for i in range(5):
            new = item[i]+item[i+1]+item[i+2]
            item.append(new)
        print item
        

        【讨论】:

        • 请通过添加一些解释为什么您的代码是问题的解决方案来避免仅使用代码的答案。请记住,此答案可以在将来对其他人有所帮助,并且信息越多越好。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-06-13
        • 2020-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多