Python 3 索引错误
Posted
技术标签:
【中文标题】Python 3 索引错误【英文标题】:Python 3 Index Error 【发布时间】:2017-02-23 10:43:20 【问题描述】:考虑以下代码:
def anadist(string1, string2):
string1_list = []
string2_list = []
for i in range(len(string1)):
string1_list.append(string1[i])
for i in range(len(string2)):
string2_list.append(string2[i])
# Test returns for checking
# return (string1_list,string2_list)
# return len(string1_list)
# return len(string2_list)
for i in range(0,len(string1_list)):
try:
if (string1_list[i]) in string2_list:
com = string1_list.pop(i)
com_index = string2_list.index(com)
string2_list.pop(com_index)
else:
pass
except ValueError:
pass
return string1_list
def main():
str1 = input("Enter string #1 >>> ")
str2 = input("Enter string #2 >>> ")
result = anadist(str1, str2)
print(result)
#Boilerplate Check
if __name__ == "__main__":
main()
在 Python 3.5.2 中运行会引发 IndexError:
Traceback (most recent call last):
File "E:\CSE107L\Practice\anadist.py", line 34, in <module>
main()
File "E:\CSE107L\Practice\anadist.py", line 29, in main
result = anadist(str1, str2)
File "E:\CSE107L\Practice\anadist.py", line 15, in anadist
if (string1_list[i]) in string2_list:
IndexError: list index out of range
而且我找不到问题所在。我写了另一个类似的代码并且有效:
def main():
lst = [1,2,3,4,5]
lst2 = [5,6,7,8,9]
for i in range(len(lst)):
if lst[i] in lst2:
com = lst.pop(i)
lst2_index = lst2.index(com)
lst2.pop(lst2_index)
else:
pass
print(lst)
if __name__ == "__main__":
main()
我觉得错误来自我形成string1_list
的方式。这段代码用于计算形成一对单词的字谜需要多少个步骤。
【问题讨论】:
迭代列表时不能删除列表中的元素。在您的代码中,列表为string1_list
【参考方案1】:
在某些情况下,您在迭代 string_list1
时会缩短它:
if (string1_list[i]) in string2_list:
com = string1_list.pop(i) # string1_list gets shorter here
但是,您的 range
不会改变。它仍然会从0
开始直到它计数到string1_list
(不包括)的原始 长度。这将在任何时候调用string1_list.pop(i)
时导致IndexError
。
一种可能的解决方案是改用while
循环:
i = 0
while i < len(string1_list):
try:
if string1_list[i] in string2_list:
com = string1_list.pop(i)
com_index = string2_list.index(com)
string2_list.pop(com_index)
else:
pass
except ValueError:
pass
i += 1
这将导致在每次迭代后检查循环终止条件。如果您从string1_list
中删除一些元素,它仍然可以,因为循环将在i
变得足够大以超出其容器的边界之前终止。
【讨论】:
【参考方案2】:您的问题是您正在通过执行string1_list.pop(i)
在for
循环内改变string1_list
。通过执行string1_list.pop(i)
,for
循环内的列表长度正在减少,但您仍在对原始列表的长度进行迭代。
您的第二批代码之所以有效,是因为您在循环的最后一次迭代中只使用了pop
。
【讨论】:
【参考方案3】:您的第二次尝试之所以有效,是因为仅在最后一个元素 5
中找到“匹配”,因此当您更改列表 lst
时,它是在 最后一次迭代期间并且没有效果。
您第一次尝试的问题是您可能会从列表的开头删除。计数器不会更新,并且在某些时候可能会达到列表中不再存在的值(它已被弹出)。尝试在输入中没有匹配项的情况下运行它,看看它是否有效。
一般来说,在迭代列表时不要改变列表。而不是:
for i in range(len(lst)):
# mutate list
'idiom',你应该选择:
for i in list(list_object): # or for i in list_object[:]:
它首先制作一个副本,并允许您通过保持变异和循环分开来变异原始 list_object
。
【讨论】:
以上是关于Python 3 索引错误的主要内容,如果未能解决你的问题,请参考以下文章
Python 3.x - iloc 抛出错误 - “单个位置索引器超出范围”
IndexError:列表索引超出范围 - python 错误