简体   繁体   中英

List index out of range error

So I am getting a list index out of range error in python again, and I can't figure out what's wrong.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

f1 = open("membrane_GO.txt","r")
new_list1 = f1.readlines()
new_list2 = new_list1
for i in range(len(new_list1)):
    if "Reactome" in new_list1[i]:
        new_list2.pop(i)
print new_list2  
f1.close()

I made sure that the a duplicated list is being modified as the primary list is iterated over, so that can't be the problem.

Appreciate any help Thanks :)

You only duplicated a reference to the list. If you want to make a separate copy of a list, use slices: list2 = list1[:] or look into the deepcopy module.

When you pop, the array size goes down. That means if the list has length 10, and you pop(0) , then the list has length 9. If you then pop(9) , which doesn't exist it will give you an out of bounds error.

Example:

>>> x = [0,1,2,3,4]
>>> print x, len(x)
[0,1,2,3,4], 5
>>> x.pop(0)
>>> print x, len(x)
[1,2,3,4], 4

This is an error in your case because you go from 0 to len(new_list1).

The approach I advise you to take is to create a new list where "Reactome" is not in new_list1[i].

You can do this easily in a list comprehension.

with open("membrane_GO.txt","r") as f:
    lines = [line for line in f.readlines() if "Reactome" not in line]
print lines

Assume that your list is initially ['a', 'b', 'c'],

then list1 = list2 = ['a', 'b', 'c']

Then you perform iteration for len(list2) , ie 3 times, Then i will take values 0, 1, and 2.

In each iteration you are removing one element from list1 .

i = 0
remove list1[0]
new list = ['b', 'c']

i = 1
remove list1[1]
new list = ['b']

i = 2
remove list[2] which does not exist.

So you will get a index out of bound error

Just to add to TigerHawks answer:

Because you have only duplicated the reference (not the list itself), when you pop() an element out of new_list2 , you also remove it from new_list1 beceause they're both references to the same list.

Say there are 'n' elements in new_list1 at the start of the loop . It will run for 'n' iterations.

Suppose then that you pop an element out of new_list2 (and so out of new_list1 as well), within the loop, you will get an index out of range error when the loop tries to access the 'nth' element of a list which now only has 'n-1' elements in it

For this to work properly use slicing to copy the list:

new_list2 = new_list1[:]

Incidentally, for i in range(len(new_list1)): is considered un-pythonic, I believe. A 'better' way would be to use enumerate :

for index, element in enumerate(new_list1):
    if "Reactome" in element:
        new_list2.pop(index)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM