For loops

You will probably have met for loops in conjunction with the range function, in simple code like this:

for i in range(5):
    print(i)

This code prints values 0, 1, 2, 3, and 4. It is more or less the Python equivalent of the following C or Java style loop:

for (i = 0; i < 5; i++)
    {
    print(i);
    }

In fact, in Python, loop indices (the variable i) not used all that often - it might even be considered un-Pythonic. Usually for loops are used to loop directly over a list or other sequence of values.

In this tutorial we will look at various other techniques available in Python to make your loops shorter and easier to read. More techniques are discussed in the articles on reverse and sort, zip and enumerate and filter.

Looping over a list

Suppose you wanted to loop over all the values in a list. New Python programmers will often write something like this:

k = ['red', 'green', 'blue']
for i in range(3):
    print(k[i])

This works perfectly well, of course, but Python provides a better way. You can loop over a list directly, without using an index variable:

k = ['red', 'green', 'blue']
for s in k:
    print(s)

Here is how the for loop works:

Loop over each element is k, and for each element:
    assign the element to variable s
    execute the body of the loop

Why this is better

Looking at the two loops, clearly the second loop has no need for the extra variable i. While that is obviously a good thing, simpler code is always better, that isn’t the main benefit. Look at the for loop line:

for s in k:

This tells you exactly what the code is doing - it is looping over the list k. Compare this with the first case:

for i in range(3):

All this tells you is that the loop will run 3 times. You have to look at the code inside the loop to figure out that each pass through the loop is actually processing the next element of k. That isn’t too hard to do in this case because the loop body only contains one line, but in a more complex loop you might have to study the code to work out what the loop is actually doing.

Looping over iterables

A for loop can loop over any iterable item. This includes sequences such as lists, tuples or strings. Looping over a tuple is exactly the same as looping over a list, but looping over a string is slightly different (but very useful):

s = 'hello'
for c in s:
    print(c)

In this case, on each pass of the loop, c contains the next character of the string. So the first time through the loop will print ‘h’, the next time will print ‘e’, and so on.

Python doesn’t have a special data type for a character. A character is represented by a string of length 1.

for can also be used with other types of iterables such as generators and list comprehensions. These objects don’t work in quite the same was as a list. A list has all its values available before the loop starts - they are just the values in the list. A generator, alternatively, doesn’t create values until it is asked for them. This is called lazy iteration

How does range work?

So, to go right back to the beginning, how does range work? range is a function, so you might simplistically think of it as a function that returns a list:

v = range(5)   # v = [0, 1, 2, 3, 4] ? No!

In fact, this is how range used to work in Python 2. But since Python 3, the range function returns a range object, that is a lazy iterable. It creates the sequence of values 0 to 4, one at a time, when the for loop requests them.

In summary, where possible, avoid using a loop counter variable, and loop over the sequence directly. This simplifies the code and makes the intent clear.