1

Is there a general rule for when a list comprehension is preferred over a for loop? For example:

A single for loop is great when converted to a comprehension:

l = []
for word in sentence:
    l.append(word)

# [word for word in sentence]

A double one might be too:

l = []
for word in sentence:
    for letter in word:
        l.append(letter)

# [letter for word in sentence for letter in word]

However, I think the readability gets pretty poor after that. For example, with ifs:

l = []
for word in sentence:
    if word.startswith('u'):
        for letter in word:
            if letter in ('a', 'b', 'c', 'o'):
                l.append(letter)

# [letter for word in sentence if word.startswith('u') for letter in word if letter in ('a', 'b', 'c', 'o')]

Is there a suggestion for the complexity of a for loop pattern where it would be worse trying to put it into a list comprehension?

3
  • 1
    I would write it both ways, and test them against each other to verify correctness. Then I would put it aside for a few days. Whichever one is more readable, without being fresh in my mind, would stay. Commented Mar 11, 2020 at 0:36
  • both are great ways, but it all comes down to preference and who you are presenting the code to. the for loop approach does shows a more 'methodical' approach as in, everything is clear as is, the comprehension way be it for list or dicts is great for getting the job done quickly. Commented Mar 11, 2020 at 0:43
  • 1
    On the topic of readability, many people dislike using lower case l for list because it looks too much like 1 :) Commented Mar 11, 2020 at 1:01

3 Answers 3

7

The answer depends on your opinion. However, since I do remember a specific piece of advice of this from an author of a book that is well regarded in the Python community, I can share the following excerpt from the book 'Fluent Python' by Luciano Ramalho:

A for loop may be used to do lots of different things: scanning a sequence to count or pick items, computing aggregates (sums, averages), or any number of other processing tasks. [...] In contrast, a listcomp is meant to do one thing only: to build a new list.

Of course, it is possible to abuse list comprehensions to write truly incomprehensible code. I’ve seen Python code with listcomps used just to repeat a block of code for its side effects.

If you are not doing something with the produced list, you should not use that syntax.

Also, try to keep it short. If the list comprehension spans more than two lines, it is probably best to break it apart or rewrite as a plain old for loop. Use your best judgment: for Python as for English, there are no hard-and-fast rules for clear writing.

Sign up to request clarification or add additional context in comments.

1 Comment

I'd agree with this, only thing to add that I haven't seen mentioned yet is: for those cases where nested list comprehension is what you need, you can define each step as a function to improve readability
2

According to this, performance can be gained.

import timeit

def squares(size):
    result = []
    for number in range(size):
        result.append(number*number)
    return result

def squares_comprehension(size):
    return [number*number for number in range(size)]

print(timeit.timeit("squares(50)", "from __main__ import squares", number = 1_000_000))
print(timeit.timeit("squares_comprehension(50)", "from __main__ import squares_comprehension", number = 1_000_000))

5.4292075
4.1652729000000015

Hope this helps.

1 Comment

Yep, list comprehensions have some optimizations which makes them faster than for loops, and also map+filter.
1

I'd add that you could always work with generators and iterators. There is no major memory overhead, but the performance may suffer unless the innermost operation is relatively costly.

from itertools import chain
sentence = "flat is better than nested"

words = sentence.split()
f_words = (w for w in words if w.startswith('f'))
f_chars = chain(*f_words)
good_chars = [c for c in f_chars if c in 'abco']

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.