# Python List Comprehensions and Michael Phelps’ Olympic Medal Cabinet

Python list comprehensions can look a bit strange at first sight. However, with a bit of practice and experience, they quickly become a go-to tool for a Python programmer.

But Python’s list comprehensions are not just syntactic sugar that condense three lines of code into one. And they’re not there just to make you look cool when you use them, either. In many instances, they’re a more efficient way of populating a list.

Michael Phelps’ carpenter will help us understand the efficiency of using Python list comprehensions through his ordeal with creating Phelps’ Olympic medal cabinet over the years.

Disclaimer: This is not a true story. And if you would have thought it is a true story without this disclaimer, then you’re reading the wrong blog!

## Building The Medal Cabinet With Standard Lists and Loops

Phelps qualified for the Syndey 2000 Olympic Games, and so he went to a local carpenter and asked him to make a medal cabinet for him, ready for when he wins medals.

The carpenter looked at the 15-year old Phelps and thought: “Who does this boy think he is? But, if he wants a medals cabinet, then I’ll make him one.”

# Sydney 2000
medal_cabinet = []

The small medal cabinet was still empty when Phelps returned from Syndey.

### Adding medals to the cabinet

Fast forward four years, and it’s Athens 2004. Phelps took his medal cabinet with him to Athens to place any medals he won in the cabinet right away. Phelps’ first event led to the first gold medal. He had space for this first medal in his empty cabinet. And the following day when he won his second medal, which he also placed in the medal cabinet.

medal_cabinet.append(
("Gold", "400m medley", "Athens 2004")
)
medal_cabinet.append(
("Bronze", "4×100m freestyle", "Athens 2004")
)

The problems started the following day when he won his third medal. There was no space in the small cabinet, so he called his carpenter, who jumped on a plane to Athens right away and started working on upgrading the cabinet. Therefore, it took a bit longer for Phelps to place his medal in the cabinet as he had to wait for the carpenter to make it bigger.

The carpenter was kept very busy over the following days. Each time Phelps won another medal, the carpenter had to get his tools out and enlarge the cabinet again.

Phelps had a feeling he would win lots of medals in his career, so he asked the carpenter to make a large cabinet. However, the carpenter thought that would be a waste of wood, and it would just take up too much space.

The carpenter stuck to his principles through Athens 2004, Beijing 2008, London 2012, and Rio 2016. He travelled with Phelps to each Olympic Games, working hard to make the cabinet a bit bigger with every new medal. But he never made it larger than it had to be.

## Retirement And Python List Comprehensions

When Michael Phelps retired from competitive swimming after Rio 2016, he called his carpenter and said: “Look, Mr Carpenter, this medal cabinet looks a bit untidy and scruffy with all these bits added on to it. Can you make me a new one please?”

The carpenter went off to his workshop and started working. He knew that he needed to build a cabinet large enough for Phelps’ 28 Olympic medals. He could now make the final cabinet in one go instead of extending it each time a new medal was added.

This is the Python list comprehensions approach to building Phelps’ medal cabinet.

## Away From The Pool

Let’s test this with another race, but not one in the pool this time. Let’s compare the standard loops and lists method with the list comprehension approach:

import time
import random

repeat = 50_000_000

# Standard method using a for loop
start_race = time.time()
container = []
for _ in range(repeat):
container.append(random.random())
print(
f"Time elapsed for 'classic' method: "
f"{time.time() - start_race}"
)

# List comprehensions
start_race = time.time()
container = [random.random() for _ in range(repeat)]
print(
f"Time elapsed for list comprehension method: "
f"{time.time() - start_race}"
)

You’ve run two time-trials here–yes, I’m sticking with the swimming race terminology, sorry! The two versions perform the same action. They create a list with 50 million random numbers. Here’s the output when I run this on my MacBook Pro:

Time elapsed for 'classic' method: 9.168850183486938
Time elapsed for list comprehension method: 6.841538906097412

There are two components of the 'classic' method that make it slower. The first is the carpenter's problem. Python doesn't know how big the list needs to be when it's created, and it needs to make it larger as it adds more items to the list. The repeated call to append() also takes up some time.

There are even faster ways to make a medal cabinet. Although this goes beyond the scope of this short post, I’ll end with a third time trial in our random-number-storage-race (which is not yet an Olympic sport):

import time
import random
import numpy as np

repeat = 50_000_000

# Standard method using a for loop
start_race = time.time()
container = []
for _ in range(repeat):
container.append(random.random())
print(
f"Time elapsed for 'classic' method: "
f"{time.time() - start_race}"
)

# List comprehensions
start_race = time.time()
container = [random.random() for _ in range(repeat)]
print(
f"Time elapsed for list comprehension method: "
f"{time.time() - start_race}"
)

# NumPy method
start_race = time.time()
container = np.random.random(repeat)
print(
f"Time elapsed for NumPy method: "
f"{time.time() - start_race}"
)

The results now look like this:

Time elapsed for 'classic' method: 9.29443097114563
Time elapsed for list comprehension method: 6.88644003868103
Time elapsed for NumPy method: 1.2364158630371094

Look out for a future blog post on NumPy.

## Final Words

Using Python list comprehensions saves a few lines of code and a bit of typing. It’s also neater, cooler, and more Pythonic than the classic for-loop-and-append() method. However, there are other benefits, too. List comprehensions can be more efficient in many cases. Just ask Michael Phelps’ carpenter.