Drop hier links of afbeeldingen om ze aan de editor toe te voegen.

Picking out one character is useful. Visiting every character, one after the other, is what lets a program count letters, search for a space or check each character of a password. That is a job for a loop.

One character at a time

A string of length 6 has indices 0 to 5, and range(len(word)) produces exactly those numbers. So a for loop over that range visits every position in the string:

word = "Python"

for i in range(len(word)):
    print(word[i])

That prints the six letters of Python, one per line. It is the same loop you used to output every item in a list: len says how many there are, range turns that into the indices, and the counter picks out one each time round. The number of repetitions is known before the loop starts, so this is a count controlled loop.

The character can be taken with a slice as well. word[i:i+1] starts at i and stops before i + 1, so it is a substring exactly one character long, and this loop prints the same six lines:

word = "Python"

for i in range(len(word)):
    print(word[i:i+1])

Both forms are correct. Exam questions often describe this as extracting one character at a time with a substring, and word[i:i+1] is the Python for that description.

Counting as you go

Put an if inside the loop and a running total around it, and the loop can count the characters that match:

word = "Mississippi"
count = 0

for i in range(len(word)):
    if word[i] == "s":
        count = count + 1

print("Number of s: " + str(count))

This is the same running-total pattern as the total you built with a for loop: the total is created before the loop, it grows inside the loop, and it is printed after the loop.

The comparison is exact, so "S" == "s" is false. To count capital and small letters alike, convert the whole word to one case with upper() or lower() before the loop starts.

Finding a character

Sometimes you need to know where a character is, not just whether it is there. The loop counter already holds the position, so store it when the character turns up:

email = "[email protected]"
at_position = 0

for i in range(len(email)):
    if email[i] == "@":
        at_position = i

print("The @ is at index " + str(at_position))
print("Name: " + email[:at_position])
print("Domain: " + email[at_position + 1:])

Once the position is known, slicing does the rest. Everything before it is email[:at_position], and everything after it starts one place further along, at at_position + 1.

A loop inside a loop

A loop can go inside another loop. The outer loop picks out one string at a time from a list, and the inner loop then works through the characters of that string:

words = ["tree", "apple", "sky"]

for w in range(len(words)):
    word = words[w]
    count = 0
    for i in range(len(word)):
        if word[i] == "e":
            count = count + 1
    print(word + ": " + str(count))

Read it from the outside in. The outer loop runs three times, once for each word. Every time it runs, the inner loop runs all the way through the letters of that one word, so it runs four times for tree, five times for apple and three times for sky.

Three details make it work:

A loop inside a loop is called a nested loop.

The short form

When a loop only needs each character and never its position, Python has a shorter way to write it:

word = "Python"

for letter in word:
    print(letter)

This prints the same six lines as the first loop on this page. There is no range and no len here: the counter, letter, holds each character itself, one after the other, instead of holding its index.

The short form is easier to read, but it cannot tell you where a character is. Finding the @ in an email address needs the index, so that loop has to use range(len(email)).

Help! My code doesn't work!

Make sure that you check for the following things:

  • The loop runs over range(len(word)), not over range(word) or range(len(word) - 1).
  • Inside the loop the character is word[i] or word[i:i+1], with the counter as the index, not a fixed number.
  • A running total or a stored position is created before the loop.
  • Comparisons between characters are exact, capital letters included.
  • In a nested loop, the two counters have different names.
  • Whatever should happen once per word, and not once per character, is indented under the outer loop only.