【问题标题】:Python - IndexError: list index out of range even though checking if emptyPython - IndexError:列表索引超出范围,即使检查是否为空
【发布时间】:2018-05-14 03:39:01
【问题描述】:

在以下代码行中出现 IndexError: list index out of range:

if tweetSplit[i] != "":

在我的代码中:

tweetSplit = tweet.split(' ') 

for i in range(len(tweetSplit)):
    #print (i)
    if not tweetSplit:
        break
    if tweetSplit[i] != "":
         #print (tweetSplit[i])
         #print (tweetSplit[i][:1])
        if tweetSplit[i][:1] == '@':
            del tweetSplit[i]

我认为通过使用“if not tweetSplit”检查 tweetSplit 是否为空,我不会遇到超出范围的错误。 这是完整的错误:

Traceback (most recent call last):
  File "parseTweets.py", line 55, in <module>
     if tweetSplit[i] != "":
IndexError: list index out of range

【问题讨论】:

  • 请向我们展示完整的追溯。

标签: python del index-error


【解决方案1】:

你的测试并没有真正起到什么作用。

当然if not tweetsplit: 检查tweetsplit 是否为空。但它不会检查 tweetsplit 是否至少是 i+1 元素长。

而且,因为您是在循环中间从tweetsplit 中删除的,所以如果您只删除一个元素,那么到最后它会比i+1 短,并引发IndexError。

这是您永远不应该在循环任何集合的过程中删除或插入的原因之一。 (但不是唯一的——例如,当您删除元素 i 时,会将所有其他元素上移一个位置,然后您检查新元素 i+1,它最初是 i+2……这意味着您错过了一个.)


如果你想建立一个符合某个规则的所有推文的集合,那么通过建立一个新列表来做到这一点要容易得多:

goodTweets = []
for tweet in tweetSplit:
    if tweet[:1] != '@':
        goodTweets.append(tweet)

或者:

goodTweets = [tweet for tweet in tweetSplit if tweet[:1] != '@']

如果您确实出于某种原因确实需要改变 tweetSplit,您可以使用一些技巧,但它们都有点难看。

建立一个新列表,然后将tweetSplit 更改为该列表:

tweetSplit[:] = [tweet for tweet in tweetSplit if tweet[:1] != '@']

或者,在不明确构建新列表的情况下执行此操作:

tweetSplit[:] = (tweet for tweet in tweetSplit if tweet[:1] != '@')

或者向后迭代。虽然len(tweetSplit) 可能会随着您的删除而改变,但 0 永远不会。 (虽然i: 中所有内容的位置可能会改变,但:i 的位置永远不会改变。)

for i in range(len(tweetSplit))[::-1]:
    if tweetSplit[i][:1] == '@':
        del tweetSplit[i]

但是,如果您尝试就地执行此操作作为性能优化,所有这些通常都会变慢。唯一可能更快的是这样的:

i = 0
while i < len(tweetSplit):
    if tweetSplit[i][:1] == '@':
        tweetSplit[i] = tweetSplit[-1]
        tweetSplit.pop()
    else:
        i += 1

【讨论】:

    【解决方案2】:

    因此,您将获得IndexError:

    del tweetSplit[i]

    发生的情况是您正在删除 tweetSplit 中的元素。这会导致 tweetSplit 的长度减少。

    要解决这个问题,不要从tweetSplit 中删除任何元素。只需遍历列表。无需删除任何元素。

    如果您不需要处理任何索引,只需在 Python 中使用 for-each 循环即可。

    for tweet in tweetSplit:
        if tweet != "" and tweet[:1] == '@':
            # Do something but don't delete any tweet from tweetSplit.
    

    【讨论】:

    • 我分配的目的是从字符串中删除以'@'开头的单词
    • @user1098432,在这种情况下,只需将任何不以“@”开头的单词放在另一个列表中。
    【解决方案3】:

    如果您不确定此时 tweetSplit[i] 是否在范围内,您可以改用类似以下内容:

    if isinstance(tweetSplit[i], str):
    

    如果 tweetSplit[i] 的值是字符串类型,这将返回一个布尔值。

    虽然您从 tweetSplit 数组中删除值的方式,您可能会遇到索引方式的问题。

    【讨论】:

      猜你喜欢
      • 2016-08-25
      • 2017-04-05
      • 2012-07-15
      • 2013-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多