Iteration using for in Python (Part 1)

Iteration using sequences

For loops in Python are a bit different from for loops in most other languages. Rather than specifying starting and ending values for the counter, you specify a sequence of items to consider. For a string or a list, all you need is the string or list itself, not the first and last indices.

For numbers, you need to use a Python data type called a range.

Definition

A Python range is an immutable sequence of integers.

It is a sequence of integers specified by a start and stop integer and a step, where the step gives the intervals between integers.

range(start, stop, step)
range(start, stop)
range(stop)

The step value can be omitted, as can the start value. We'll talk about these in a moment.

What is tricky is that unlike the ending value for a counter in pseudocode, which is one of the numbers used, here the stop value is not in the sequence of numbers.

Caution

The stop value is not in the sequence.


Ranges in Python

Let's first look at a range with a positive step. Each element is less than stop when step is positive.

range(4, 12, 3)

In this case the start value 4 is included, as well as any value that can be obtained by repeatedly adding the step value 3, as long as the stop value 12 is not reached.

So here we start with 4, add 3 to get 7, add 3 again to get 10, and then stop, since the next number would be greater than 12. Thus the following sequence is generated:

4, 7, 10

Keep in mind that range(4, 13, 3) would have the same values, since the stop value 13 cannot be part of the range.

As a second example, consider a case where start is greater than stop and step is negative. Each element is greater than stop when step is negative.

range(12, 4, -3)

The numbers included are then 12, 9, and 6, but not 3:

12, 9, 6

If the step is omitted, it has the default value of 1.

range(5, 10)

This range will include 5, 6, 7, 8, and 9, but not 10, since stop is never included:

5, 6, 7, 8, 9

When start is also omitted, it has the default value of 0.

range(3)

The numbers in this case would be 0, 1, and 2, but not 3:

0, 1, 2

Translating from pseudocode to Python

In translating from pseudocode, we have the usual addition of a colon and even indentation.

Pseudocode

for i from a to b action

Indent

Python

for i in range(a, b + 1):
    action

Indent evenly

We also have the usual convention of indenting four spaces.

Python convention

Indent four spaces.

There is also a change in the way the counter values are represented.

Caution

To obtain all values from a to b (including both a and b), use a stop value of b + 1 in Python.

In pseudocode, both the starting and ending values are possible values of the counter. In Python, since the stop value is not in the range, we need to give a bigger value than in pseudocode.


Types of for loops

In addition to using a range, we can also specify that our counter iterates through items in a list or characters in a string.

for num in range(a, b+1):
    action
for item in ["a", "b", "c"]:
    action
for char in "caterpillar":
    action

We didn't need to use these particular names for the counters; use any identifier for the counter variable.


Using the variable in and out of the loop

In order to understand how Python sets and increments the counter, we're going to try to introduce errors by setting and printing its value at different points in a program.

def after_loop():
    for x in range(3):
        print(x)
    print(x)

after_loop()

We start by checking what happens to the value of x after the end of the for loop:


0
1
2
2

We see that x still has a value, namely the ending value for the loop, which is 2, the largest value in the range.

def before_loop():
    print(x)  
    for x in range(3):
        print(x)
   
before_loop()

Now we print the value of x before the for loop.


Traceback (most recent call last):
  File "<string>", line 6, in <module>
  File "<string>", line 2, in before_loop
UnboundLocalError: local variable 'x' referenced before assignment

Not surprisingly, there is an error message, since x has not yet been defined.

def param(x):
    print(x)
    for x in range(3):
        print(x)
    print(x)
    
param("cat")

In this example, we use the name x for both the input parameter and the name of the counter for the for loop.


cat
0
1
2
2

The first print statement shows the value of the parameter; the print statements in the for loop show that x is reassigned to be the value of the counter, and the last print statement shows that outside the loop x has the ending value.

def inside():
    x = "x"
    print(x)
    for x in range(3):
        print(x)
    print(x)
    
inside()

This time we use x as the name of a local variable inside the function.


x
0
1
2
2

The first print statement shows that x has the assigned value before the loop is entered. Then, like in the previous example, x is reassigned to be the counter for the for loop, and keeps the value when the loop ends.

def print_then_change():
    for x in range(3):
        print(x)
        x = x + 5
    print(x)
    
print_then_change()

We now try changing the value of x within the loop.


0
1
2
7

The first three print statements show that the counter is reset each time the loop starts, so that the values that are printed within the loop are 0, 1, and 2.

But look what happens outside of the loop. On the last time through the loop, x gets the value 2, which is then updated to 7 inside the loop, and since there are no more iterations, x is not changed again. After the loop is exited, the print statement shows that the value is still 7.

def change_then_print():
    for x in range(3):
        x = x + 5
        print(x) 
    print(x)
    
change_then_print()

Here we update the value of x in the loop and print after the update happens.


5
6
7
7

That is, when x is set to 0 as the loop is entered, the value x + 5, which is 5, is printed.

The next time through the loop x is set to 1, and now the value x + 5, which is 6, is printed.

Finally x is set to 2, and now the value x + 5, which is 7, is printed. Since x is not reset after the last iteration, the last time it is printed, it retains the value 7.