For and While Loops in Python

roller coaster under white clouds and blue sky

A loop is a programming structure that repeats a set of instructions until a condition is met. You can use loops to for example iterate over a list of values, accumulate sums, repeat actions, and so on. In Python, you can use for and while loops to loop through sequences.

For example, here is a simple for loop:

names = ["Ann", "Sofie", "Jack"]

for name in names:
    print(name)

And here is a simple while loop:

i = 0

while(i < 5):
    print(i)
    i += 1

Today, you are going to learn

  • How to use for and while loops in Python (beginner-friendly)
  • How to control the flow of a for and while loops (beginner-friendly)
  • Alternative ways to create for and while loops in Python (intermediate)
  • How to use Python’s Itertools module for looping-related tasks (intermediate)

Let’s jump into it!

For Loops in Python

In Python, a for loop is used to iterate over an iterable (such as a list or dictionary).

  • Iterable is any Python object over which you can iterate. For example a list or a dictionary.

This is the basic syntax of a for loop:

for val in sequence:
    # some action

Where val is the variable in which the elements inside the sequence are stored one by one during each iteration.

For instance, let’s loop through a list of names and print them:

names = ["Ann", "Sofie", "Jack"]

for name in names:
    print(name)

Output:

Ann
Sofie
Jack

For…Else Loop in Python

You can use an else statement in a for loop. The else block is executed when the looping comes to an end

For instance:

for i in range(3):
    print(i)
else:
    print('Looping completed.')

Output:

0
1
2
Looping completed.

Range() Function in Python—Keep Track of The Loop Index

So far you’ve seen a for loop that picks elements one by one from a collection.

However, sometimes you may want to use the traditional approach to looping: start from number x and end to y. This can be useful for example when you want to associate an index with each element.

You can use the built-in range() function to achieve this. This function returns a range object that is a sequence of numbers in the given range. The range function excludes the second argument.

For example:

print(list(range(0,5)))

Output:

[0, 1, 2, 3, 4]

For instance, let’s print the names of a group of persons and their relative positions in a queue using the range() function:

queue = ["Jack", "Ann", "Sofie"]
length = len(queue)

for i in range(0, length):
    name = queue[i]
    print("{} is at {}. position".format(name, i + 1))

Output:

Jack is at 1. position
Ann is at 2. position
Sofie is at 3. position

Find more for loop examples here.

While Loops in Python

Now you know the basics of using a for loop. Let’s next take a look at the while loop.

In python, you can use a while loop to repeat a block of statements until a given condition is satisfied. When the condition becomes false the looping terminates.

For instance:

i = 0

while(i < 5):
    print(i)
    i += 1

Output:

0
1
2
3
4

You can use while loops to iterate over iterables, such as lists of numbers. You need to know the length of the list and keep track of an index. This is because you have to get the values from a list based on an index and terminate the loop before the end.

For instance:

numbers = [1, 2, 3]
list_length = len(numbers)

index = 0
while index < list_length:
    print(numbers[index])
    index += 1

Output:

1
2
3

While…Else Loop in Python

You can use an else statement in a while loop. The else block is executed when the looping condition becomes false.

For instance:

i = 0
while(i < 2):
    print("i is less than 2")
    i += 1
else:
    print("The condition is False.")

Output:

i is less than 2
i is less than 2
The condition is False.

Nested loops in Python

Now you know how to use both for and while loops in Python.

It is worthwhile to understand that you can create a loop inside a loop. This construct is called a nested loop.

For example, here is a nested for loop. In other words, a for loop inside of another for loop:

groups = [(3,2,0), (2,1,3), (7,1,1)]

for triple in groups:
    for value in triple:
        print(value)
    print("")

Output:

3
2
0

2
1
3

7
1
1

Nested While Loop Example

Let’s repeat the above example with a nested while loop:

groups = [(3,2,0), (2,1,3), (7,1,1)]

i,j = 0, 0
while i < len(groups):
    triple = groups[i]
    while j < len(triple):
        value = triple[j]
        print(value)
        j += 1
    i += 1
    j = 0
    print("")

Output:

3
2
0

2
1
3

7
1
1

Break, Continue, and Pass—Control the Flow of a Loop

You can control the flow of the execution of a loop using break and continue statements. These work the same way for both while loop and for loops.

  • The break statement terminates the loop and proceeds execution at the first statement following the loop.
  • The continue statement terminates the current iteration of the loop and proceeds to the next iteration.

Break Example

The break statement breaks out the loop and continues the program execution from the next possible line after the loop.

For instance:

numbers = [1,4,3,2,5,19,5,0]

target = 3

for number in numbers:
    print("Current number", number)
    if number == target:
        print("Target found. Exiting...")
        break

Output:

Current number 1
Current number 4
Current number 3
Target found. Exiting...

Continue Example

The continue statement skips the “rest of the loop” and begins the next iteration.

n = 10

while n > 0:              
   n -= 1
   if n > 3:
      continue
   print('Current value:', n)

Output:

Current value: 3
Current value: 2
Current value: 1
Current value: 0

The continue statement jumps out of the current iteration and starts the next one. If n > 3 the continue statement is not reached anymore. This means the print action is going to take place.

Now you know how to control the flow of the execution of a loop using break and continue statements. Let’s take a look at the pass statement, which is a way to ignore an empty loop.

Pass Statement

In Python, it is not possible to leave a loop (or anything that comes after colon) empty. But there is a dedicated keyword pass for that.

For instance, if you want to pass the implementation of a for loop, do it like this:

for i in range(10):
    pass

One-Liner For Loops Using List Comprehensions

Now you know the basics of loops in Python. It’s time to take a look at how to compress for loops using comprehensions. This can help reduce the lines of code and improve code quality.

List comprehension is a built-in feature in Python. You can replace for loops with one-liner expressions.

The syntax for a list comprehension looks like this:

[expression for element in sequence]

List Comprehension Examples

Let’s print a list of numbers using a comprehension:

numbers = [1, 2, 3]

[print(number) for number in numbers]

Output:

1
2
3

This example is not practical, because a list comprehension is meant to create a new iterable based on an existing one.

To demonstrate this, let’s square a list of numbers:

numbers = [1, 2, 3, 4]

squared_numbers = [num * num for num in numbers]
print(squared_numbers)

Output:

[1, 4, 9, 16]

You can add a condition at the end of the comprehension. For instance, let’s filter odd numbers out of a list:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

even_numbers = [num for num in numbers if num % 2 == 0]
print(even_numbers)

Output:

[2, 4, 6, 8, 10]

List Comprehension Performance in Python

A list comprehension is ~10% faster than a regular for loop.

For example, here are the runtime averages using both for loop and list comprehension to square a list of 1M integers.

For squaring a list of numbers, comprehension is around 10% faster.

However, the slight performance advantage is not a reason to use comprehensions. The goal of using comprehension is to avoid unnecessary lines of code and improve readability. Using lengthy comprehensions for performance does not make sense if it sacrifices the code quality.

Other Comprehension Types in Python

List comprehension is not the only comprehension type there is. Python also supports:

To keep it short, I’m not going to show examples of these. Furthermore, these comprehensions are almost identical to a list comprehension.

Comprehensions Summary

  • A list comprehension can improve code quality and reduce the number of lines of code.
  • Avoid writing lengthy list comprehensions. This makes the code hard to follow.
  • Every list comprehension can be written as a for loop, but not the other way around.
  • A comprehension gives a slight performance advantage over a regular for loop.

Enumerate() Function in Python

Do you remember the example where you used a range() function in a for loop to keep track of the index of the current element? Even though it is a valid approach, there is a better one: The built-in enumerate() function. You can use it with for loops to keep track of the index of the current element.

For instance:

queue = ["Ann", "Sophie", "Jack"]

for position, person in enumerate(queue):
    print(f"{person} is at position {position}")

Output:

Ann is at position 0
Sophie is at position 1
Jack is at position 2

How Does enumerate() Work

The enumerate() function takes two arguments:

  • An iterable object, such as a list.
  • An optional start index, which is 0 by default.

It works by returning an enumerate object that contains the elements of the iterable coupled with an index. This is handy when looping: You don’t need to keep track of an index of the current element as enumerate() does it for you.

Let’s demonstrate what enumerate() does.

queue = ["Ann", "Sophie", "Jack"]
print(list(enumerate(queue)))

Output:

[(0, 'Ann'), (1, 'Sophie'), (2, 'Jack')]

The list elements are coupled with indexes. This makes it possible to know the index of each element in a for loop:

for position, person in enumerate(queue):
    print(f"{person} is at position {position}")

Change the Initial Value of the Index in enumerate()

The enumerate() function accepts a second optional argument. This is the start index which is 0 by default. If you want indexing to start from somewhere else, please define the start argument.

For example, let’s start indexing from 10:

queue = ["Ann", "Sophie", "Jack"]

for position, person in enumerate(queue, start=10):
    print(f"{person} is at position {position}")

Output:

Ann is at position 10
Sophie is at position 11
Jack is at position 12

This concludes the basics of looping in Python using for and while loops. The following chapters are intermediate Python that show you for and while loop alternatives.

Replace For and While Loops in Python with Map() and Filter() Functions

Now that you know the basics of looping in Python, let’s move to intermediate concepts.

In Python, there are built-in functions dedicated to looping. These work by applying a lambda function on each element on the list and returning a transformed version of the list.

Before showing an example of using map() and filter(), let’s learn what a lambda function is.

Lambda Expressions in Python

A lambda function is a function without a name. It takes any number of arguments and only has one expression. To demonstrate, here is a lambda function that squares a number:

lambda x : x ** 2

For instance, let’s square a number using lambda function:

squared_num = (lambda x : x ** 2)(3.0)
print(squared_num)

Output:

9.0

Lambdas are useful when the functionality is needed for a short period of time. In other words, when you don’t want to waste resources by creating a separate method. A great example is when passing it into a map() function.

Map() Function in Python

The map() function is a replacement to a for a loop. It applies a function for each element of an iterable. The map() function accepts two arguments:

  • A function that is applied for each element in the list (a lambda expression)
  • A list on which to operate

The map() function returns is a map object. This can easily be converted to a list with the list() function.

To demonstrate this, let’s square a list of numbers:

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

# Compute the squares
squares = map(lambda x: x ** 2, numbers)

print(list(squares))

Output:

[1, 4, 9, 16, 25]

Filter() Function in Python

The filter() function is used to filter elements based on a condition. The filter function takes two arguments:

  • A lambda expression—a function that is executed for each element in the list
  • An iterable, such as a list, on which it operates

For instance, let’s filter the even numbers of a numbers list:

numbers = [1, 2, 3, 4, 5, 6]

# filter even numbers
even_nums = filter(lambda x: x % 2 == 0, numbers)

print(list(even_nums))

Output:

[2, 4, 6]

Itertools—Efficient and Easy Looping in Python

Itertools is a Python module. It provides you with functions to perform tasks related to looping over iterables. An Itertool method returns an iterator object.

Before seeing examples, here is a short definition for an iterator an iterable:

  • Iterable is any Python object over which you can iterate. For example a list or a dictionary.
  • An iterator is an object used to iterate over an iterable. An iterator only cares about the current element of the iterable and knows how to obtain the next element. This makes it memory efficient. Every iterator is iterable by nature, but not the other way around.

Let’s go through some useful Itertools methods. Without these, you would need to write complicated nested loops to get the job done.

Accumulate a List of Numbers

To calculate an accumulated sum you could use a for loop. But with the help of Itertools, you can use itertools.accumulate().

Here is an illustration of accumulation:

Illustration of a running sum of a list
Accumulate a running sum using Itertools

Here is the code:

from itertools import accumulate

a = [1,2,3,4]

acc = accumulate(a)

print(list(acc))

Output:

[1, 3, 6, 10]

If you want to accumulate something else than the sum, pass another argument to the accumulate() method. This argument is a function that is applied to the elements.

For example, let’s accumulate the product:

Illustration of a running product of a list of numbers
Accumulate running product

To do this, pass operator.mul to the accumulate() method to make it accumulate the product instead of the sum:

from itertools import accumulate
import operator

a = [1,2,3,4]

prods = accumulate(a, func=operator.mul)

print(list(prods))

Output:

[1, 2, 6, 24]

Group a Collection of Elements with groupby() Function

You can group an iterable by a criterion using itertools.groupby() method.

Let’s group the following list of numbers into groups of numbers less than three and greater than equal to three:

from itertools import groupby

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

group = groupby(a, key=lambda x: x < 3)

for k, v in group:
    print(k, list(v))

Output:

True [1, 2]
False [3, 4, 5]

Compute the Cartesian Product

The Cartesian product is a group of all the pairs from two lists:

Cartesian product

To compute the Cartesian product, you could use for loops. But Itertools provides you with a way to obtain it by using the itertools.product() method. It returns the Cartesian product as an iterator object.

For example:

from itertools import product

a = [1,2]
b = [3,4]

prod = product(a,b)

print(list(prod))

Output:

[(1, 3), (1, 4), (2, 3), (2, 4)]

Obtain All the Permutations

Given a group of items, you can find all the possible ways to arrange them with itertools.permutations().

For instance:

from itertools import permutations

a = [1,2,3]

perms = permutations(a)

print(list(perms))

Output:

[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]

Get All the Combinations

Use itertools.combinations() to find all the combinations (of size n) of a group of items.

For instance, let’s find all the pairs you can form from a list of three numbers:

from itertools import combinations

a = [1,2,3]

combs = combinations(a, 2)

print(list(combs))

Output:

[(1, 2), (1, 3), (2, 3)]

Infinite Iterators—A Valid Infinite Loop

Infinite iterators make it possible to give an infinite stream of numbers. It is like a “valid infinite loop”.

It isn’t possible to store an infinite number of elements in memory. But because iterators only care about the current element, it’s possible to produce an infinite stream of items using an iterator.

Let’s go through examples.

Count

You can use itertools.count() method to loop numbers from a starting number to infinity.

As an example, let’s create an infinite stream of numbers starting from 10:

from itertools import count

for i in count(10):
    print(i)

Output:

10
11
12
.
.
.

Cycle

You can use Itertools to juggle a list of numbers using the itertools.cycle() method. The cycle repeats forever.

For instance:

from itertools import cycle

a = [1,2,3]
for i in cycle(a):
    print(i)

Output:

1
2
3
1
2
3
.
.
.

Repeat

Repeat the same number to infinity using itertools.repeat().

For example:

from itertools import repeat

for i in repeat(10):
    print(i)

Output:

10
10
10
10
.
.
.

Conclusion

A loop is an important programming concept. It’s a process of repeating actions based on criteria.

Loops in Python are either for loops or while loops.

There are useful concepts that can make your looping easier:

  • Comprehensions
  • Built-in looping functions map() and filter()
  • Itertools library for computing complex but common tasks involving loops.

Thanks for reading. Happy coding!

I’d love to join your LinkedIn network. Feel free to connect Artturi Jalli.

Further Reading

For loop examples in Python

Share on facebook
Facebook
Share on google
Google+
Share on twitter
Twitter
Share on linkedin
LinkedIn
Share on pinterest
Pinterest

Leave a Comment

Your email address will not be published. Required fields are marked *