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

Question:

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
Asked By: Intrepid Diamond

||

Answers:

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.

Answered By: idjaw

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].

Answered By: Ozgur Vatansever

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.

Answered By: Jared Mackey

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.

Answered By: lvc
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.

Answered By: Ahsanul Haque

There is a recipe for partitioning in the itertools documentation:

def partition(pred, iterable):
    'Use a predicate to partition entries into false entries and true entries'
    # partition(is_odd, range(10)) --> 0 2 4 6 8   and  1 3 5 7 9
    t1, t2 = tee(iterable)
    return filterfalse(pred, t1), filter(pred, t2)

You can use it like:

positives, negatives = partition(lambda value: value < 0, originals)
Answered By: Peter Wood

I don’t really know why no one writes about list elements appropriation. When you use simple for element in list and you tried to write some info in the list element – that not works. Only when you use the index of element, like list[0]="Test value" you can rewrite it.

Answered By: Ashen One

list’ object cannot be interpreted as an integer:

if you want to play with the list items so you have to tell the length to compiler.

In another case where you want to use directly just the range function chk below:

original_list = 3
for i in range(original_list):
print("yes")

in the above scenario, there is no len function because we are using a single integer but if you will use a list,tuple or set so you have to use len function to compile successfully

Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.