Python Tutorial – List Comprehensions

This Python Tutorial post will introduce a very cool technique for Object Oriented guy like me: List Comprehensions. It provides way to create new lists while doing some operations to elements in the list.

List Comprehensions

Lets take a simple example how you would create a list of numbers in a range multiplied with two. Quite school example, but hang on.

1

2

3

4

5

6

values=[]

fornumber inrange(5):

values.append(number *2)

print values

""" Prints: [0, 2, 4, 6, 8] """

This gets the job done. For object oriented guy this would be standard way to do this. There’s luckily shorter way to do same with comprehension.

1

2

print[number *2fornumber inrange(5)]

""" Prints: [0, 2, 4, 6, 8] """

Inside brackets first part is expression and after that there is for clause. Comprehension can has an optional part that can contain zero or more for and if clauses.

Here is an example of if clause in list comprehension.

1

2

print[number *2fornumber inrange(5)ifnumber%2==0]

""" Prints: [0, 4, 8] """

Now comes the part that things get a bit ugly. Here are two versions of flattening loops.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

numbers=[

[12,13,14],

[15,16,17],

[18,19,20],

]

print[number forrow innumbers fornumber inrow]

""" Prints[12, 13, 14, 15, 16, 17, 18, 19, 20] """

all=[]

forrow innumbers:

fornumber inrow:

all.append(number)

print all

""" Prints[12, 13, 14, 15, 16, 17, 18, 19, 20] """

I find the first version completely unusable because it looks very messy. I would gladly use latter version because you can understand it with one glimpse.

Conclusion

I started this post with saying that List Comprehensions are cool. They still are and somewhat usable way to shorten your code.
But.

List Comprehension comes with a price. They are almost always harder to read than their clearer versions. Think twice before writing something just for less lines of code.

Comments

I think you are missing a core concept here: functional programming. And with it, immutability. I agree that the syntax of Python’s list comprehensions might not be ideal. Just saying that nested loops are always easier to reason about than multiple expressions in a list comprehension still rubs me the wrong way.

With functional constructs you don’t (or at least shouldn’t) mutate anything, you get new collections back. With imperative nested loops which change the guts of things all over the place it gets hard to see what’s going on very quickly.

Also, I think multiple expressions in comprehensions are more readable if you put them in separate lines: