Python: for loops - for i in range(0,len(list) vs for i in list

45,738

Solution 1

In your case, since you don't need to use the index of the items in the list, you can just iterate over it using for in:

>>> for item in original_list:
...     if item < 0:
...         ...

If you want to iterate over the indexes of items in your list, use for in range(..):

>>> for i in range(len(original_list)):
...     if original_list[i] < 0:
...         ...

Alternatively, you might also want to use enumerate() if you need both item and index in loop's body:

>>> for i, item in enumerate(original_list):
...    if item < 0:
...        ...

By this way, you also eliminate the use of original_list[i].

Solution 2

The construction range(len(my_sequence)) is usually not considered idiomatic Python. It focuses your code on lower level mechanics than what we usually try to write, and this makes it harder to read. Because of this, using range here is mostly seen as a holder from people used to coding in lower level languages like C.

See, for example, Raymond Hettinger's talk Transforming Code into Beautiful Idiomatic Python - one of the first things he recommends is exactly changing for i in range(len(sequence)) into for item in sequence where ever it appears; he then goes on to mention enumerate and zip to cover situations where you might otherwise be tempted to revert to using range. He also mentions that the idiomatic way is faster. Aside from Python builtin types being (unsurprisingly) optimised to run idiomatic constructs quickly, it isn't hard to see why this could be true of certain other data structures - for example, a linked list can have much faster sequential than random access, meaning that loops relying on my_linked_list[i] could become a quadratic time operation rather than a linear one.

You can see similar advice from time to time if you follow the [python] tag over at codereview.SE.

Solution 3

If you open up your interpreter and do the following:

help(range)

You will get this:

Help on built-in function range in module __builtin__:

range(...)
    range(stop) -> list of integers
    range(start, stop[, step]) -> list of integers

    Return a list containing an arithmetic progression of integers.
    range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
    When step is given, it specifies the increment (or decrement).
    For example, range(4) returns [0, 1, 2, 3].  The end point is omitted!
    These are exactly the valid indices for a list of 4 elements.

As you can see from the description, it is the way the range works. It takes a starting position, and then a stopping position, and then an optional step to go up by x each time.

edit

To answer based off of your comment, the reason why you are getting an index out of range, is because when you do this:

for i in arr:
    print(arr[i])

That won't work, because for i in arr will give you the values of each item in the array. So, what you are doing then is actually putting in a value in to arr as if it is the index. But it is not.

When you do this:

for i in range(0, len(arr))

What is happening here is you are getting an incremental value that is based on the size of the array, so that way you can use that value as an index to your list.

Solution 4

lst=[1,2,3,4]

for i in range(lst):
    print lst[i]

You can't do that. Because:

TypeError: range() integer end argument expected, got list.

What you can do is:

 for i in range(len(lst)): #i is the index here
     print lst[i]

Output: 1 2 3 4

Or,

 for i in lst: #i is the value here
     print i

Output:

1
2
3
4

Actually, range is not idiomatic python. You can avoid it. If you need index, you can use enumerate like below:

 for i,j in enumerate(lst): #i is the index and j is the value here
 print i,j

Hope it is clear to you now.

Solution 5

Don't use range to iterate over a list of values. Do for item in list. If you need the index use enumerate.

for index, value in enumerate(original_list):
    print index
    print value

Or

for item in original_list:
    if item < 0:
        neg_list.append(item)
    else:
        pos_list.append(item)

You were probably getting the exception using for item in original_list: because you were trying to do neg_list.append(original_list[item]) which would could lead to something like original_list[-3] or original_list[6] which would be out of range.

Share:
45,738
Intrepid Diamond
Author by

Intrepid Diamond

Updated on July 05, 2022

Comments

  • Intrepid Diamond
    Intrepid Diamond almost 2 years

    This is a really simple python mechanics question. Why can't I just say for i in range original_list instead of for i in range(0, len(original_list)). Do people usually use range over the former? Thanks!

    # "If I give you an array with negative and positive numbers (i.e. {3,2,-3,6,4,-7}) and asked you to sort it so that the negative numbers appeared first but you didn't change the relative order of the remaining numbers, how would you do it? (i.e. the final result would be {-3,-7,3,2,6,4}).
    
    original_list = [3, 2, -3, 6, 4, -7]
    pos_list = []
    neg_list = []
    
    for i in range(0, len(original_list)):
        if original_list[i] < 0:
            neg_list.append(original_list[i])
        else:
            pos_list.append(original_list[i])
    
    print neg_list + pos_list
    
  • Intrepid Diamond
    Intrepid Diamond over 8 years
    It throws me an out of range exception if I try to run it with for item in list... Do you know why?
  • Intrepid Diamond
    Intrepid Diamond over 8 years
    I understand how range works. What I'm wondering is why running the code with for i in original_list doesn't do the same thing at range(0,len(original_list). If I do the former, it throws me an out of range exception.
  • Intrepid Diamond
    Intrepid Diamond over 8 years
    Which one is most efficient? Is it situation by situation? Should I make sure to only use enumerate if I actually need both?
  • Intrepid Diamond
    Intrepid Diamond over 8 years
    puu.sh/kxR7Y/69a2c9924b.png, so use method 1 if I only need values and use enumerate/method 3 if I need indices as well?
  • Intrepid Diamond
    Intrepid Diamond over 8 years
    So, just double checking... puu.sh/kxR7Y/69a2c9924b.png, so use method 1 if I only need values and use enumerate/method 3 if I need indices as well?
  • Ahsanul Haque
    Ahsanul Haque over 8 years
    @IntrepidDiamond If you want to access index through range(), use method 1. If index isn't needed, use method2. If you want index without using range, use method 3
  • Matthias
    Matthias over 8 years
    The standard is for item in original_list.