Skip to article frontmatterSkip to article content

Chapter 3.4 - For loops

Like while loops, for loops will execute an indented code block as long as a condition is met.

The useful aspect of for loops is that this logic does not need to be explicitly determined by the coder. And, you can avoid infinite loops!

Chapter 3.4.1 - Basic for loop syntax:

my_list = [1, 2, 3, 4, 5]

for i in my_list:
    print(i)
    # do something with i

Each for loop has 3 major components:

  1. iterable: a data type that is able to interface with a for loop and has multiple values within it.
  2. iteration: each step in the loop, where the iteration variable set by the programmer is modified based on values in the iterable.
  3. iterator: the mechanism that works behind the scenes to set values and determine if the loop should continue

The preconditions for a for loop require an iterable data type. These types include (but are not limited to):

  1. list
  2. tuple
  3. dict

Each of these composite data types are considered iterable, which is just a fancy way of saying that they contain multiple items and a for loop can automatically serve up each item that it contains. For example, an int is not an iterable because it is only one value, but a list of int variables within a list can be served to a for loop through the list that contains these variables.

Each step of the loop (i.e., each time the indented code block is executed) is called an iteration. During an iteration, the value served by the for loop changes in the order the values appear in the list.

For example, the following list (which is an iterable):

my_list = [1, 2, 3, 4]

Would serve to the for loop the value 1 during the first iteration. The second iteration would serve the value 2, and so on.

The iterator is the magic that occurs in the background of a for loop that does multiple things for you:

  1. It checks to see if there are more items to visit in the iterable. If not, the loop ends

  2. During each iteration, it accesses the values in the iterable at each index in the order in which they appear. The iterator then sets this value equal to a variable that is named by the programmer that can be used in the current iteration

Consider the above for loop:

my_list = [1, 2, 3, 4, 5]

for i in my_list:
    print(i)
    # do something with i

The equivalent process can be explicitly demonstrated by a while loop:

my_list = [1, 2, 3, 4, 5]

index = 0

while (index < len(my_list)):

    i = my_list[index]
    
    print(i)
    
    # do something with i
    
    index = index + 1

Notice the extra steps in the while loop:

  1. setting an index variable to 0 to start at the beginning of the list
  2. determining a condition (i.e., index < len(my_list) when the loop should stop
  3. accessing each value in the list based on the index variable and setting it equal to i
  4. incrementing the index by 1 to visit the next item in the list, or to cause the while loop condition to result in False and stop the loop.

Thus, for most cases, we would want to use a for loop to avoid all of the potential pitfalls and bugs that could pop up when using a while loop.

Examples of the for and while loops above.

while loop:

my_list = [1, 2, 3, 4, 5]

index = 0

while (index < len(my_list)):

    i = my_list[index]
    
    print(i)
    
    # do something with i
    
    index = index + 1
1
2
3
4
5

for loop equivalent

my_list = [1, 2, 3, 4, 5]

for i in my_list:
    print(i)
    # do something with i
1
2
3
4
5

Chapter 3.4.2 - Iterators

There are multiple built-in iterators that are incredibly useful and very common in Python programs. These iterators typically encapsulate common use-cases for steping through iterables (e.g., a list).

range

One common iteration is to step through a sequence of numbers. For example, you may want to visit all numbers between 1 and 100. Using the code pattern associated with the for loop above, you might start writing the following code:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 .....]

You immediately recognize that would require typing many numbers. If you have any case where you need 1000, 10000, or 1000000000 number sequences, you can see where this approach would be limiting.

However, Python has a solution--the built-in range data type. This is a special type of list that contain a list of int values with attributes defined by the programmer. Specifically, the programmer can provide the start, end, and steps (i.e., spacing between numbers). This allows you to type as few as two numbers to produce a sequence of many int values.

The following pattern is associated with range:

for number in range(start, finish, step):
    print(number)
    # do stuff with number

Here is a working version below. Modify the start, finish, and step values by typing an int and pressing enter when prompted below:

start = int(input("start (int): "))
finish = int(input("finish (int): "))
step = int(input("step (int): "))

print(f"for loop output for this loop: for number in range({start}, {finish}, {step})")
for number in range(start, finish, step):
    print("number =", number)
    # do 
    # stuff 
    # with 
    # number
start (int):  1
finish (int):  10
step (int):  2
for loop output for this loop: for number in range(1, 10, 2)
number = 1
number = 3
number = 5
number = 7
number = 9

Example: # iterate through a list of integers that go from 0 to 10

By default, python will treat using only one number as the “finish” number, and the first number will default to 0 and the step will default to one. The following iterator is equivalent to range(0, 11, 1)

print("for number in range(11):")
for number in range(11):
    print(number)
for number in range(11):
0
1
2
3
4
5
6
7
8
9
10

that is much easier than this:

print("for number in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:")
for number in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
    print(number)

print("---")
for number in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]:
0
1
2
3
4
5
6
7
8
9
10
---

Example: iterate through a list of every 10th integer from 0 to 100

print("Output from for number in range(0, 100, 10)")
for number in range(0, 100, 10):
    print(number)
Output from for number in range(0, 100, 10)
0
10
20
30
40
50
60
70
80
90

enumerate

Another common pattern is to keep track of how many times the loop has executed. For example, you might have a list of data from hours or days, and you want to print out that the data are from “Day 1” or “Day 2”.

enumerate will keep track of this information and provide the value during each iteration. This can also be useful for identifying the index associated with each value.

Here is the interactive example above, except with enumerate included and wrapped around range:

start = int(input("start (int): "))
finish = int(input("finish (int): "))
step = int(input("step (int): "))

print(f"for loop output for this loop: for number in range({start}, {finish}, {step})")
for idx, number in enumerate(range(start, finish, step)):
    print(f"For iteration #{idx}, the value of number is {number}")
    # do 
    # stuff 
    # with 
    # number
start (int):  1
finish (int):  10
step (int):  2
for loop output for this loop: for number in range(1, 10, 2)
For iteration #0, the value of number is 1
For iteration #1, the value of number is 3
For iteration #2, the value of number is 5
For iteration #3, the value of number is 7
For iteration #4, the value of number is 9

Chapter 3.4.3 - Stacks and queues

These are special types of list that are used for a specific purpose and various algorithms. This approach uses the pop() function to remove the last item that was added to the lift (last in, first out) and set it equal to a variable.

Stacks

The premise of a stack is Last In First Out (LIFO)

Rules of a stack:

  1. allow values to be added at any time
  2. the last value to be added will be the first to be removed when the stack is accessed
stack = []

# print empty stack
print("Empty stack", stack)

# add values to a stack
stack.append(5)
stack.append(4)
stack.append(3)
stack.append(2)
stack.append(1)

# print empty stack
print("Stack with 5 values", stack)

# access values from stack using LIFO
print("First value accesed from stack:", stack.pop())
print("Stack after pop()", stack)
Empty stack []
Stack with 5 values [5, 4, 3, 2, 1]
First value accesed from stack: 1
Stack after pop() [5, 4, 3, 2]

Queue

The same as a stack, except the premise of a queue is First in First Out (LIFO)

Rules of a queue:

  1. allow values to be added at any time
  2. the first value to be added will be the first to be removed when the queue is accessed (pop(0))
queue = []

# print empty queue
print("Empty queue", queue) # prints []

# add values to a queue
queue.append(5)
queue.append(4)
queue.append(3)
queue.append(2)
queue.append(1)

# print empty queue
print("queue with 5 values", queue) # prints [5, 4, 3, 2, 1]

# access values from queue using FIFO
print("First value accesed from queue:", queue.pop(0)) # prints 5
print("Queue after pop()", queue) # prints [5, 4, 3, 2]
Empty queue []
queue with 5 values [5, 4, 3, 2, 1]
First value accesed from queue: 5
Queue after pop() [4, 3, 2, 1]

Chapter 3.4.5 - Dictionary iterators

These follow the same rules as the above examples, except they have different iterator keywords that need to be explicitly written out:

  1. .keys(): iterate through only the keys in the dictionary
  2. .values(): iterate only though the values and not the keys in the dictionary
  3. .items(): iterate through BOTH the keys and values

Basic dictionary iterator example:

## Basic dictionary iterator example
dict_name = {'test': 1}

for key in dict_name.keys():
    print(key) # prints test

for value in dict_name.values():
    print(value) # prints 1

for key, values in dict_name.items():
    print(key, value) # prints test 1

print("---")
test
1
test 1
---

Example: A weather related use-case that iterates through both keys and values in a dictionary to print a message.

observations = {'temperature': [42, 53, 23, 59, 60], 'dew point': [33, 45, 15, 50, 50]}

for variable, observations in observations.items():

    # observations is now a list and can be treated like a list
    for temperature in observations:

        if temperature >= 32:
            print(f"The {variable} is {temperature} F and you should not expect ice!")
        else:
            print(f"The {variable} is {temperature} F and you should expect ice!")

        C = (temperature - 32) * 5/9
        K = C + 273.15

        print(f"The temperature in celisus is {C:.2f} C and the temperature in Kelvin is {K:.2f} K")
        print("")
The temperature is 42 F and you should not expect ice!
The temperature in celisus is 5.56 C and the temperature in Kelvin is 278.71 K

The temperature is 53 F and you should not expect ice!
The temperature in celisus is 11.67 C and the temperature in Kelvin is 284.82 K

The temperature is 23 F and you should expect ice!
The temperature in celisus is -5.00 C and the temperature in Kelvin is 268.15 K

The temperature is 59 F and you should not expect ice!
The temperature in celisus is 15.00 C and the temperature in Kelvin is 288.15 K

The temperature is 60 F and you should not expect ice!
The temperature in celisus is 15.56 C and the temperature in Kelvin is 288.71 K

The dew point is 33 F and you should not expect ice!
The temperature in celisus is 0.56 C and the temperature in Kelvin is 273.71 K

The dew point is 45 F and you should not expect ice!
The temperature in celisus is 7.22 C and the temperature in Kelvin is 280.37 K

The dew point is 15 F and you should expect ice!
The temperature in celisus is -9.44 C and the temperature in Kelvin is 263.71 K

The dew point is 50 F and you should not expect ice!
The temperature in celisus is 10.00 C and the temperature in Kelvin is 283.15 K

The dew point is 50 F and you should not expect ice!
The temperature in celisus is 10.00 C and the temperature in Kelvin is 283.15 K

Chapter 3.4.6 - Practice

Create a dictionary of rock or cloud names, where each name has their affiliated descriptions and a date when you saw the rock or cloud.

Once you complete the dict, use the dict iterator to print a message similar to the following:

The cirrus cloud looks wispy and feathery and is usually high in the sky. I saw a cirrus cloud on 09/06/2025.
The obsidian rock is black and shiny and is formed by volcanoes. I saw an obsidian rock on 09/20/2025.