What is a list comprehension and when should I use one?

Short answer

A list comprehension builds a new list in one expression: [expr for item in iterable if condition]. Use it when you are producing a collection; use a normal loop when you are performing an action.

python
squares = [n ** 2 for n in range(1, 11)]
evens   = [n for n in range(20) if n % 2 == 0]
names   = [v["title"] for v in catalogue if v["views"] > 200]

Read it left to right: the square of n, for each n in that range.

#The shape

python
[EXPRESSION for ITEM in ITERABLE if CONDITION]

The if is optional. An if/else goes before the for, because then it is part of the expression:

python
[n if n > 0 else 0 for n in numbers]     # clamp negatives to zero

#Dict and set versions

python
{word: len(word) for word in words}      # dict comprehension
{v["track"] for v in catalogue}          # set comprehension

#When not to use one

Also: if the body does something rather than produces something — printing, writing a file, calling an API — use a normal for loop. Building a list of Nones and discarding it is a misuse of the syntax.

#Drop the brackets when feeding an aggregate

python
total = sum(v["views"] for v in catalogue)

Round brackets make a generator: items are produced one at a time instead of building an intermediate list.