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.”
He made a small cabinet, sold it to Phelps, and forgot about this cabinet and the boy soon after.
# 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.
Factory-Made Cabinet
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.
Further reading
- James Timmins on Real Python: When to Use a List Comprehension in Python
- Python Geeks article: List Comprehensions in Python
- Leodanis Pozo Ramos on Real Python: List Comprehension section in Python’s .append(): Add Items to Your Lists in Place
You may also enjoy reading about Monty and The White Room analogy for understanding programming.
Become a Member of
The Python Coding Place
Video courses, live cohort-based courses, workshops, weekly videos, members’ forum, and more…
Subscribe to
The Python Coding Stack
Regular articles for the intermediate Python programmer or a beginner who wants to “read ahead”