Python Intermediate Concepts Tutorial

List Comprehensions

List comprehensions provide a concise way to create lists.

Comparison of Multi-line Program Versus List Comprehension

Here's a simple example in which we create a new list of squares.

We'll loop over this list below.

In [28]:
list(range(1, 5))
[1, 2, 3, 4]

In Python, we can iterate over just range(1, 5) to iterate over 1 through 4 including the value 4.

range(1, 5) gives us an immutable sequence. We can iterate over it but we cannot simply index a value from it.

In [29]:
small_range = range(1, 5)

Each number in the list will put to the power of 2, otherwise called number squared.

number squared operation number squared
1 12 1
2 22 4
3 32 9
4 42 16

Our result should be a list: [1, 4, 9, 36]

Multi-line program

In [30]:
squares = []
for number in small_range:
In [31]:
[1, 4, 9, 16]

List comprehension

A list comprehension consists of brackets [] containing an expression followed by a for clause.

In [32]:
[number**2 for number in small_range]
[1, 4, 9, 16]

We can assign a variable to the result of this list comprehension.

In [33]:
squares_again = [number**2 for number in small_range]
In [34]:
[1, 4, 9, 16]

Additional Simple List Comprehension Examples

You can also use any number of if clauses in a list comprehension.

We can create a new list to remove all mentions of the name dan.

In [38]:
names = ['sean', 'dan', 'bill', 'jamie', 'dan']
In [41]:
names_without_dan = [name for name in names if name!='dan']
In [42]:
['sean', 'bill', 'jamie']

Similar to our initial example of creating squares of numbers, we can use a list comprehension to create a list of tuples with each tuple a pair of a value and its square.

In [43]:
[(number, number**2) for number in range(1, 5)]
[(1, 1), (2, 4), (3, 9), (4, 16)]

Measuring the Performance of List Comprehensions

Often times, using list comprehensions over traditional multi-line programs can result in code that executes in a shorter period of time. This is especially useful if you're doing operations on large datasets.

We'll mimic the example above with the only difference being we'll iterative over all numbers from 1 to 12000000 - that's 1.2 million operations!

In Jupyter Notebooks, we can use %%time to measure the runtime of code blocks.

In [35]:
big_range = range(1, 12000001)

Multi-line program

In [36]:

many_squares = []
for number in big_range:
CPU times: user 5.33 s, sys: 284 ms, total: 5.62 s
Wall time: 5.64 s

List Comprehension

In [37]:

many_squares_again = [number**2 for number in big_range]
CPU times: user 3.98 s, sys: 259 ms, total: 4.24 s
Wall time: 4.25 s

This list comprehension takes over 25% less time to compute than the multi-line program.

Performance results of list comprehensions vary. Sometimes, your program will run in significantly less time; other time, runtime may be on part with a multi-line program.

I'd encourage you to try both in your programs to see what works best.