For Loops#

A while loop continues for as long as a condition is met, a for loop on the other hand repeats for every element in an iterable.

Table of Contents

Part 1: Syntax#

The syntax for a for loop is:

for VAR in ITERABLE:
    BODY

VAR

variable name (or comma-separated list of names) to assign each item to

ITERABLE

object to iterate over.

BODY

statements to execute where VAR will be used

Here’s a simple example that iterates over a list of strings.

Listing 76 for loop example#
1for word in ["apple", "banana", "cherry"]:
2    letter = word[0].upper()
3    print(f"{letter} is for: {word}.")

Part 1.1: Exercise#

Exercise 29 (Movies)

Iterate over a list of movies and print each one out using a for loop.

Part 2: Iterables and iterators#

Some objects in Python are iterable–that is, an object that can be iterated over. For example, list, tuple and range objects are all iterable.

All iterables can be converted to an iterator, which is an object that will keep returning elements until there are no more left.

To demonstrate this we’ll create a colors list then convert the it to a colors_iterator using the iter() function.

colors = ["red", "green", "blue"]
colors_iterator = iter(colors)

Then we’ll keep requesting items using the next() function, until we encounter a StopIteration exception.

next(colors_iterator)
'red'
next(colors_iterator)
'green'
next(colors_iterator)
'blue'
next(colors_iterator)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[5], line 1
----> 1 next(colors_iterator)

StopIteration: 

Part 2.1: Exercise#

Exercise 30 (Iterators)

  1. Create a list containing the letters in your name assigned to the variable letters.

  2. Convert the list to an iterator using the iter() function and assign it to the variable letters_iterator.

  3. Keep calling next() with the argument letters_iterator until you encounter a StopIteration exception.

Part 3: Under the hood#

Now that you know what iterables and iterators are, we demystify for loops.

Lets look at the syntax again.

for VAR in ITERABLE:
    BODY

Here’s what’s happening behind the scenes:

  1. ITERABLE is converted to an iterator object using iter(), or rather its magic method

  2. Each iteration, next() is called, and the results are assigned to VAR

  3. The BODY statements are executed

  4. When next() results in a StopIteration exception it is discarded and the loop ends

Lets revisit our for loop example, and see if we can deconstruct the behavior of a for loop. First we’ll create a houses list, and convert it to a houses_iter using the iter() function.

# create iterable
houses = [
  "Arryn",
  "Baratheon",
  "Greyjoy",
  "Lannister",
  "Martell",
  "Stark",
  "Targaryen",
  "Tully",
  "Tyrell",
]

# create iterator
houses_iter = iter(houses)

Now we’ll call next() in a while loop, and assign the results to name.

# loop forever
while True:
    # assign VAR to the results of next()
    name = next(houses_iter)

    # BODY statements
    print(f"House {name}")
House Arryn
House Baratheon
House Greyjoy
House Lannister
House Martell
House Stark
House Targaryen
House Tully
House Tyrell
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[7], line 4
      1 # loop forever
      2 while True:
      3     # assign VAR to the results of next()
----> 4     name = next(houses_iter)
      6     # BODY statements
      7     print(f"House {name}")

StopIteration: 

This is close, but we’re still seeing that StopIteration exception. To suppress it we’ll need a try-except block.

# create iterator
houses_iter = iter(houses)

# loop forever
while True:

    # any code that may raise an exception goes under the try header
    try:

        # assign VAR to the results of next()
        name = next(houses_iter)

    # the type of exception that we want to catch
    # instead of raising it, the body statements will be executed
    except StopIteration:

        # StopIteration means there are no more elements, so exit the loop
        break

    # BODY statements
    print(f"House {name}")
House Arryn
House Baratheon
House Greyjoy
House Lannister
House Martell
House Stark
House Targaryen
House Tully
House Tyrell

Now we have a while loop that replicates the behavior of a for loop. Here they are side by side.

houses = [
  "Arryn",
  "Baratheon",
  "Greyjoy",
  "Lannister",
  "Martell",
  "Stark",
  "Targaryen",
  "Tully",
  "Tyrell",
]

houses_iter = iter(houses)

while True:
    try:
      name = next(houses_iter)
    except StopIteration:
      break

    print(f"House {name}")
houses = [
  "Arryn",
  "Baratheon",
  "Greyjoy",
  "Lannister",
  "Martell",
  "Stark",
  "Targaryen",
  "Tully",
  "Tyrell",
]

for name in houses:
  print(f"House {name}")

Part 3.1: Exercise#

Exercise 31 (Game Characters)

  1. Make a list of game character roles.

  2. write a while loop

    1. Convert the list to an roles_iter iterator using the iter() function

    2. Make a while loop with the condition True

    3. Get each role element from the roles_iter by calling next()

    4. Print the role

    5. Suppress the error with a try-except block

  3. write a for loop

    1. Make a for loop with the variable name role and the iterable roles

    2. Print the role

Part 4: Multiple assignment#

Depending on the type passed to it, next() may sometimes return more than one value. The classic example of this is dict.items().

suites = {
  "heart": "red",
  "diamond": "red",
  "club": "black",
  "spade": "black",
}
suites_iterator = iter(suites.items())
next(suites_iterator)
('heart', 'red')

You can see that next() returns a tuple that contains two items. We can assign this to a single variable, which will then contain the entire tuple.

item = next(suites_iterator)
item
('diamond', 'red')

Or we could use multiple assignment to assign each item in the tuple to a corresponding variable. There must be the same number of variables to the left of the = as there are items in the tuple separated by ,.

suit, color = next(suites_iterator)
suit
'club'
color
'black'

Lets put this assignment fanciness in a while loop.

suites_iterator = iter(suites.items())

while True:
    try:
      suit, color = next(suites_iterator)
    except StopIteration:
      break

    print(f"The {suit} suit is {color}.")
The heart suit is red.
The diamond suit is red.
The club suit is black.
The spade suit is black.

And lets see how it looks in a for loop.

for suit, color in suites.items():
    print(f"The {suit} suit is {color}.")
The heart suit is red.
The diamond suit is red.
The club suit is black.
The spade suit is black.

Here they are side by side.

 1suites = {
 2  "heart": "red",
 3  "diamond": "red",
 4  "club": "black",
 5  "spade": "black",
 6}
 7
 8suites_iterator = iter(suites.items())
 9
10while True:
11    try:
12      suit, color = next(suites_iterator)
13    except StopIteration:
14      break
15
16    print(f"The {suit} suit is {color}.")
1suites = {
2  "heart": "red",
3  "diamond": "red",
4  "club": "black",
5  "spade": "black",
6}
7
8for suit, color in suites.items():
9    print(f"The {suit} suit is {color}.")

Part 4.1: Exercise#

Exercise 32 (Game Tools)

  1. Make a dict of game character tools, where the key is the role and the value is a tool.

  2. write a while loop

    1. Convert tools.items() to an tools_iter iterator using the iter() function

    2. Make a while loop with the condition True

    3. Get each role and tool element from the tools_iter by calling next()

    4. Print the "A roles favorite tool is their trusty: tool."

    5. Suppress the error with a try-except block

  3. write a for loop

    1. Make a for loop with the variable name tool and the iterable tools

    2. Print the tool

Part 5: Incrementing#

Sometimes we need to keep track of the number associated with each item in an iterable. One way to do this would be to increment a number each iteration.

i = 0
rainbow = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]

for color in rainbow:
  print(i, color)
  i += 1
0 red
1 orange
2 yellow
3 green
4 blue
5 indigo
6 violet

An easier way to do this is to use the enumerate() function which returns an iterator. Each iteration it yields a tuple containing the count and the next item.

Lets take a look at what happens when we pass the rainbow list to enumerate(). (Notice that we convert the iterator to a list so we can see its contents.)

list(enumerate(rainbow))
[(0, 'red'),
 (1, 'orange'),
 (2, 'yellow'),
 (3, 'green'),
 (4, 'blue'),
 (5, 'indigo'),
 (6, 'violet')]

To use this in a for loop, we’ll call enumerate() on the ITERABLE. Then we’ll change VAR so that it assigns both i and color.

rainbow = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]

for i, color in enumerate(rainbow):
  print(i, color)
0 red
1 orange
2 yellow
3 green
4 blue
5 indigo
6 violet

We can change the number that emumerate() starts at by passing an optional second argument.

rainbow = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]

for i, color in enumerate(rainbow, 1):
  print(i, color)
1 red
2 orange
3 yellow
4 green
5 blue
6 indigo
7 violet

But what happens if you want to enumerate an iterable that yields multiple items per iteration? Is it possible to assign the number and the other items to their respective variable names?

Lets take a look at what happens when we pass a dict.items() treatable to enumerate().

suites = {
  "heart": "red",
  "diamond": "red",
  "club": "black",
  "spade": "black",
}

list(enumerate(suites.items()))
[(0, ('heart', 'red')),
 (1, ('diamond', 'red')),
 (2, ('club', 'black')),
 (3, ('spade', 'black'))]

The iterable now yields a tuple containing the count, and each item is a tuple containing the key and value like so: (COUNT, (KEY, VALUE))

To use this in a for loop, simply enclose the key-value tuple in parenthesis.

suites = {
  "heart": "red",
  "diamond": "red",
  "club": "black",
  "spade": "black",
}

for i, (suit, color) in enumerate(suites.items(), 1):
    print(f"{i}. The {suit} suit is {color}.")
1. The heart suit is red.
2. The diamond suit is red.
3. The club suit is black.
4. The spade suit is black.

Part 5.1: Exercise#

Exercise 33 (Number Names)

Use the enumerate function to print the numerical values 1 through 5 next to the names of those numbers ("one" through "five").

Need help?
  1. Make a list assigned to the variable numbers containing the names of the numbers "one" through "five".

  2. Write a for loop using the variable names i and name that iterates over the value returned from calling enumerate() with the arguments numbers and 1.
    In the for loop:

    • print i and name

Example output:

Listing 81 example output#
1 one
2 two
3 three
4 four
5 five

Part 6: Comparing loops#

Lets do some side-by-side comparisons of the same code written as a while loop and a for loop.

On the left will be the while loop code and on the right will be the for loop code.

Part 6.1: list iteration with next()#

In this example we’ll iterate over a colors list.

On the left we will use a while loop to iterate over a list by converting it using the iter() function, then calling next() on the resulting iterator.

On the right the same code as a for loop, where the use of iter() and next() happens behind the scenes.

Listing 83 Iter example A-1: list iteration via while loop#
colors = ["red", "green", "blue"]
colors_iterator = iter(colors)
while True:
    try:
        color = next(colors_iterator)
    except StopIteration:
        break
    print(color)
Listing 84 Iter example A-2: list iteration via for loop#
colors = ["red", "green", "blue"]
for color in colors:
  print(color)

Part 6.2: range iteration with next()#

Lets do the same comparison with a range object.

On the left we will use a while loop to iterate over a range by converting it using the iter() function, then calling next() on the resulting iterator.

On the right is the same code as a for loop.

Listing 85 Iter example B-1: range iteration via while loop (error surpressed)#
numbers = range(1, 4)
numbers_iter = iter(numbers)
while True:
  try:
    num = next(numbers_iter)
  except StopIteration:
    break

  print(num)
Listing 86 Iter example B-2: range iteration via for loop#
numbers = range(1, 4)
for num in numbers:
  print(num)

Part 6.3: list iteration with subscription#

In this example we’ll iterate over the colors list as before, except now we’ll use an incrementing index number to get each element using bracket notation or subscription.

While you can achieve similar results this way, subscription is not a perfect mirror of an analogous for loop. It’s not quite as accurate in terms of what goes on under the hood and in fact not all iterable objects provide access via bracket notation.

Even so, the this familiar pattern may help to shed some light on for loop behavior.

Listing 87 Bracket example C-1: list iteration via while loop#
colors = ["red", "green", "blue"]
idx = 0

while idx < len(colors):
    color = colors[idx]
    print(color)
    idx += 1
Listing 88 Subscript example C-2: list iteration via for loop#
colors = ["red", "green", "blue"]

for color in colors:
  print(color)

Part 6.4: string iteration with subscription#

In this example we’ll iterate over each letter in the string word using bracket notation.

Listing 89 Bracket example D-1: str iteration via while loop#
word = "flibbertigibbet"
idx = 0

while idx < len(word):
    letter = word[idx]
    print(letter)
    idx += 1
Listing 90 Bracket example D-2: list iteration via for loop#
word = "flibbertigibbet"

for letter in word:
  print(letter)

Part 7: Exercises#

Part 7.1: Game Skills#

Exercise 34 (Game Skills)

  1. Make a list of game character skills.

  2. write a while loop

    1. Assign the idx var to 0

    2. Make a while loop with the condition that idx is less than the length of skills

      1. Get each element from skills using bracket notation idx and assign it to skill

      2. Increment idx

      3. Print the skill

  3. write a for loop

    1. Make a for loop with the variable name skill and the iterable skills

      1. Print the skill

Part 7.2: Weekdays#

Exercise 35 (Weekdays)

Print the weekday names horizontally and seperated by |.

  1. Make a WEEKDAYS list of names.

  2. Use a for loop to iterated over each day.

  3. Print each day centered to the same size (somewhere around 10 to 20) with seperated by vertical bars (|).
    Hint: using the .center() method.

Example output:

|   Monday   |  Tuesday   | Wednesday  |  Thursday  |   Friday   |

Reference#

Glossary#

For Loops#

iterable#

An object that can be iterated over. One that provides the .__iter__() method used by the iter() function.

iterator#

An object that provides a .__next__() method, used by the built in function next(), which, when called repeatedly, will keep returning elements until there are no more left.

multiple assignment#

Assigning the contents of an itrable to multiple variables on the same line with the same number of variables names to the left of the = as there are items in the iterable seperated by ,.
For example:
from, to = (1, 100)
first, last = "a", "b"

See also#