January 14, 2022

Tutorial: How to Write a For Loop in Python

How to Write a For Loop in Python

Most tasks we encounter in our everyday lives are repetitive. While these tasks may become boring to humans, computers can handle repetitive tasks quickly and efficiently. We’ll learn how in this tutorial.

This tutorial is for Python beginners, but if you’ve never written a line of code before, you may want to complete our free-to-start Python Fundamentals course because we won’t be covering basic syntax here.
To understand how computers can help us with repetitive tasks, let’s work through a scenario to sort a population of 10,000 people into age groups. Let’s assume that the process requires two steps:

  1. Look up the age of the person
  2. Record in the appropriate age group

To successfully register each member of the population into their age group, we will complete the two-step process ten thousand times. When we successfully complete this process once, we have iterated once. When we complete this process for the entire population, we have iterated 10,000 times.

Iteration means executing this two-step process many times. After one iteration, we repeat the process from the start, making a loop. Therefore, a loop is the set-up that implements an iteration.

There are two types of iterations: definite and indefinite. With definite iteration, you loop through an object with fixed size. This means that you know the number of iterations that your program will perform from the start. If you don’t know the number of iterations from the beginning, and you require some form of conditional logic to terminate the loop, it is an indefinite iteration.

What Is a For Loop in Python?

In Python, we use the for loop to traverse iterables and iterators. It is an example of definite iteration, and the syntax for a simple Python for loop operation looks like this:

for item in iterable:
statement

Not all data types support this kind of operation. We call data types that support for loop operations iterables. Iterables include string, list, set, frozenset, dictionary, tuple, DataFrame, range, and array. Iterables are objects that can implement the __iter__() and __next()__ methods.

Iterators also support for loop operations. An iterator is the data type formed when the __iter__() method is called on an iterable. Therefore, all iterables have their iterators. There are, however, some data types that are iterators by default. Examples include zip, enumerate, and generator. Iterators can only implement __next__() method.

Operations requiring more than one for loop are nested for loop operations. The syntax for an operation with two for loop looks like this:

for item_one in iterable_one:
    for item_two in iterable_two:
        statement

A for loop has an optional else block that executes when the for loop operation is exhausted. The for-else syntax with two for loop operations looks like this:

for item_one in iterable_one:
    for item_two in iterable_two:
        statement:
    else:
        statement
else:
    statement

To convert an iterable to an iterator object, we can either call the __iter__() method or the iter() function. The syntax for both operations is slightly different, but they achieve the same result:

# Using the __iter__() method
iterable.__iter__()

# Using the iter() function
iter(iterable)

The iter() function calls the __iter__() method to perform this conversion.

When we have an iterator object, we can return the items in the iterator object with the __next__() method or the next() function. The syntax for this operation looks like this:

# Using the __next__() method
iterator.__next__()

# Using the next() function
next(iterator, default)

The next() function calls the __next__() method to return the next item in the iterator. When you have exhausted all the items in the iterator, the __next__() method raises the StopIteration exception to let you know that the iterator is now empty. This exception is not raised if the next() function is called with a default value. It returns the default value instead.

A for loop operation in Python is similar to calling the __iter__() method, and the __next__() method one or more times until the items in the iterator are exhausted, as we shall see in the following sections

Iterating Through a String

Strings are examples of immutable data types. Once created, its value cannot be updated. We established that you use a for loop for an object with a definite size. We use the len() function to get the size of a string.

string = "greatness"
len(string)  # 9

We also claimed that strings are iterable and that they can implement the __iter__() and __next__() methods. The code snippet below shows the implementation of these methods:

string = "greatness"
string_iter = string.__iter__()
print(string_iter.__next__())
print(string_iter.__next__())
print(string_iter.__next__())

Output

g
r
e

The __iter__() method converts the data type to string iterator, and the __next__() method returns the items in the string one after the other. If you use the __next__() method enough times, you will return all the items in the string.

We can perform a similar operation using a for loop. There are two ways to do this. In the first method, you loop through the string:

# Looping through a string
for item in string:
    print(item)

Output

g
r
e
a
t
n
e
s
s

In the second method, you loop through the string’s index and access the items in the string with their index value. We get the index of a string from its size with the range function.

Output

g
r
e
a
t
n
e
s
s

Iterating Through a List

Unlike strings, lists are mutable. Like strings, they are iterables. Therefore, lists implement the __len__(), __iter__(), and __next__() methods:

list_string = ['programming', 'marathon', 'not', 'sprint']

print(list_string.__len__())

list_iter = list_string.__iter__()
print(list_iter.__next__())
print(list_iter.__next__())
print(list_iter.__next__())
print(list_iter.__next__())

Output

4
programming
marathon
not
sprint

The __iter__() method converts the list object to a list iterator, and the __next__() method returns the items in the iterator one after the other. We can perform similar operations on a list using a for loop:

for item in list_string:
    print(item)

Output

programming
marathon
not
sprint

Iterating Through a Tuple

A tuple is a collection of objects separated by commas. Its operations are very similar to a list, but a tuple is immutable. A tuple is an iterable, and it implements the __len__(), __iter__(), and __next__() methods:

tuple_string = 'programming', 'marathon', 'not', 'sprint'

print(tuple_string.__len__())

tuple_iter = tuple_string.__iter__()
print(tuple_iter.__next__())
print(tuple_iter.__next__())
print(tuple_iter.__next__())
print(tuple_iter.__next__())

Output

4
programming
marathon
not
sprint

The iter() function converts the tuple object to a tuple iterator, and the next() function returns items in the iterator one after the other. We can perform similar operations with a for loop:

for item in tuple_string:
    print(item)

Output

programming
marathon
not
sprint

Iterating Through Set and Frozenset

In Python, set is a mutable object. Frozenset has similar properties to set, but it is immutable. Set and frozenset have definite sizes, and they are iterables. Therefore, using a combination of the next() and iter() function on a set and a frozenset object gives results similar to the for loop:

set_object = set(['programming', 'marathon', 'not', 'sprint'])

set_iter = iter(set_object)
print(next(set_iter))
print(next(set_iter))
print(next(set_iter))
print(next(set_iter))

frozenset_object = frozenset(['programming', 'marathon', 'not', 'sprint'])

frozenset_iter = iter(frozenset_object)
print(next(frozenset_iter))
print(next(frozenset_iter))
print(next(frozenset_iter))
print(next(frozenset_iter))

for item in set_object:
    print(item)

for item in frozenset_object:
    print(item)

Output

not
programming
sprint
marathon

The iter() function converts set and frozenset objects to set iterator, while the next() function returns the items in the set iterator one after the other.

Iterating Through a Dictionary

A Python dictionary is an object that stores data as key-value pairs. The key of a dictionary must be the immutable data type. Therefore, strings, integers, and tuples are appropriate dictionary keys. Items in a dictionary can be assessed with their keys. Like the iterables discussed before it, a dictionary has a definite size and implements the iter() and next() functions:

dict_score = {'Kate': [85, 90, 95], 'Maria':[92, 90, 94], 'Ben':[92, 85, 91]}

print(len(dict_score))

dict_iter = iter(dict_score)
print(next(dict_iter))
print(next(dict_iter))
print(next(dict_iter))

Output

3
Kate
Maria
Ben

The iter() function converts the dictionary object to a dictionary_keyiterator. Notice from the name of the new object and from the output that the next operation iterates over the dictionary keys. We can perform similar operations using a for loop:

for key in dict_score:
    print(key)

Output

Kate
Maria
Ben

You can also iterate over a dictionary values using the following syntax:

for value in dict_score.values():
    print(value)

Output

[85, 90, 95]
[92, 90, 94]
[92, 85, 91]

The output of the above code snippet is a Python list, which is an iterable. When we have two iterables, we can apply the nested for loop syntax:

for value in dict_score.values():
    for item in value:
        print(item)

Output

85
90
95
92
90
94
92
85
91

We have seen examples of how to iterate over a dictionary’s keys and values separately. However, we can do both at once with the following syntax:

for key, value in dict_score.items():
    print(key)
    for item in value:
        print(item)

Output

Kate
85
90
95
Maria
92
90
94
Ben
92
85
91

Iterating Through Zip

We use the zip() function for parallel iteration. This means that you can iterate over two or more iterables at the same time. It returns a tuple containing parallel items of the iterables passed through it:

import string

letters = string.ascii_lowercase[:5]  # abcde
index = range(len(letters))  # 01234

for tup in zip(index, letters):
    print(tup)

Output

(0, ‘a’)
(1, ‘b’)
(2, ‘c’)
(3, ‘d’)
(4, ‘e’)

Unlike the other iterables we have seen that convert the iterables to their iterators with the iter() function, the zip() function doesn’t require this step because it is an iterator. It uses the next() function to return items as a tuple one after the other

zip_iter = zip(index, letters)
print(next(zip_iter))
print(next(zip_iter))
print(next(zip_iter))

Output

(0, ‘a’)
(1, ‘b’)
(2, ‘c’)

We can also use the zip() function for parallel iteration with iterables of different sizes:

letters = ['a', 'b', 'c']  # length equals 3
numbers = [1, 2, 3, 4]  # length equals 4

for tup in zip(letters, numbers):
    print(tup)

Output

(‘a’, 1)
(‘b’, 2)
(‘c’, 3)

The size of the result equals the size of the smallest iterable, as shown in the code snippet above.

Iterating Through DataFrame

A pandas DataFrame is a mutable two-dimensional tabular data structure. It is an iterable and implements the len(), iter(), and next() functions:

import pandas as pd

df = pd.DataFrame({
    'Physics': [90, 92, 89, 94],
    'Math': [100, 98, 100, 99]}, 
    index=['Oliver', 'Angela', 'Coleman', 'Agatha'])

df_iter = iter(df)
print(next(df_iter))
print(next(df_iter))

Output

Physics
Math

The iter() function converts a DataFrame to a map object, which is an iterator. The next() function returns the column names. This is similar to using a for loop:

for col in df:
    print(col)

Output

Physics
Math

We may want to iterate over the rows of the DataFrame, not their column names. We can achieve this with the df.iterrows() method. It returns a tuple of each row starting with the index:

for row in df.iterrows():
    print(row)

Output

(‘Oliver’, Physics 90
Math 100
Name: Oliver, dtype: int64)
(‘Angela’, Physics 92
Math 98
Name: Angela, dtype: int64)
(‘Coleman’, Physics 89
Math 100
Name: Coleman, dtype: int64)
(‘Agatha’, Physics 94
Math 99
Name: Agatha, dtype: int64)

Iterating Through Enumerate

Like the zip() function, the enumerate() function is an iterator. Therefore, it doesn’t need the iter() function to operate. We use it to iterate over an iterable. It returns a tuple containing the index and value associated with that index. We use the start attribute to set the beginning index value

list_string = ['programming', 'marathon', 'not', 'sprint']

list_enumerate = enumerate(list_string, start=5)
print(next(list_enumerate))
print(next(list_enumerate))
print(next(list_enumerate))
print(next(list_enumerate))

Output

(5, ‘programming’)
(6, ‘marathon’)
(7, ‘not’)
(8, ‘sprint’)

We can get similar results using a for loop:

for item in enumerate(list_string, start=5):
    print(item)

Output

(5, ‘programming’)
(6, ‘marathon’)
(7, ‘not’)
(8, ‘sprint’)

Iterating Through Generator

In Python, a generator is a special function that uses the yield instead of the return statement. We call it a lazy iterator because it doesn’t store all its content in memory; it returns them one after the other when the next() function is called:

def square_generator(n):
    for i in range(1, n+1):
        yield i**2

squares = square_generator(4)
print(next(squares))
print(next(squares))
print(next(squares))
print(next(squares))

Output

1
4
9
16
We can achieve the same result with a for loop:

for item in square_generator(4):
    print(item)

Output

1
4
9
16

For Loop and List Comprehension

List comprehension is a way to create a list from any iterable. It’s a fun way to simplify a for loop that ends with the append statement.

import string

string_iter = string.ascii_lowercase[:5]

ord_list = []
for item in string_iter:
    ord_list.append(ord(item))

print(ord_list)

Output

[97, 98, 99, 100, 101]

The above code snippet written as a list comprehension looks like this:

ord_list = [ord(item) for item in string_iter]
print(ord_list)

Output

[97, 98, 99, 100, 101]

We use list comprehension to simplify a nested for loop like this:

multiples_two = [2, 4, 6, 8]
multiples_three = [3, 6, 9, 12]

result = []
for first in multiples_two:
    for second in multiples_three:
        result.append(first*second)     
print(result)

Output

[6, 12, 18, 24, 12, 24, 36, 48, 18, 36, 54, 72, 24, 48, 72, 96]

Written with list comprehension, we use the following code snippet:

result = [first * second for first in multiples_two for second in multiples_three]
print(result)

Output

[6, 12, 18, 24, 12, 24, 36, 48, 18, 36, 54, 72, 24, 48, 72, 96]

Set comprehension is very similar to list comprehension. The output data type is a set instead of a list. The nested for loop example represented as a set comprehension is:

result = {first * second for first in multiples_two for second in multiples_three}
print(result)

Output

{6, 12, 18, 24, 36, 48, 54, 72, 96}

The size of the results from set comprehension is smaller than list comprehension; this is because items aren’t repeated in a set.

Break and Continue Keywords in a For Loop

Sometimes, we want to terminate the execution of a loop when a certain condition is met. We use the break keyword to break out of a loop. For example:

result = [6, 12, 18, 24, 12, 24, 36, 48, 18, 36, 54, 72, 24, 48, 72, 96]

for item in result:
    if item > 40:
        break
    print(item)

Output

6
12
18
24
12
24
36

The break keyword stops the execution of the for loop, but sometimes we may want to skip an item that meets a certain condition and continue with our iteration. This is what the continue key work does.

for item in result:
    if item > 40:
        continue
    print(item)

Output

6
12
18
24
12
24
36
18
36
24

For-Else Loop

The for loop has an optional else statement. The else block executes if the for loop doesn’t encounter a break keyword during execution. For example:

result = [6, 12, 18, 24, 12, 24, 36, 48, 18, 36, 54, 72, 24, 48, 72, 96]

for item in result:
    if item > 40:
        break
    print(item)
else:
    print('For loop does not encounter break keyword')

Output

6
12
18
24
12
24
36

In the above code snippet, the for loop encounters a break keyword and terminates the execution of the loop. Therefore, the else block doesn’t execute. Without the break keyword, the else block executes after the for loop:

for item in result:
    if item > 40:
        continue
    print(item)
else:
    print('For loop does not encounter break keyword')

Output

6
12
18
24
12
24
36
18
36
24

For loop does not encounter break keyword

Conclusion

We use the for loop to traverse an iterable with definite size. The __int__() method converts the iterable to its iterator, and the __next__() method returns the items in the iterable one after the other. A for loop operation is similar to calling the __iter__() method on an iterable to get an iterator, as well as the __next__() method one or more times until the iterator is empty. We discussed simple and nested for loops, how for loops work for different data types, and how break and continue keywords work inside a loop.

If you’d like to keep exploring for loops in Python, check out this other Dataquest tutorial for beginners. For a more advanced look at for loops in Python, check out this Dataquest tutorial.

Dataquest

About the author

Dataquest

Dataquest teaches through challenging exercises and projects instead of video lectures. It's the most effective way to learn the skills you need to build your data career.

Learn data skills for free

Headshot Headshot

Join 1M+ learners

Try free courses