Python - IndexError: list index out of range even though checking if empty

Python - IndexError: list index out of range even though checking if empty

我在以下代码行收到 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

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

if isinstance(tweetSplit[i], str):

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

尽管从 tweetSplit 数组中删除值的方式,您可能 运行 会遇到索引方式的问题。

你得到 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.

你的测试并没有多大用处。

确定 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