Filtering
An if at the end keeps only some items:
evens = [n for n in nums if n % 2 == 0]
That is the filter position, and it takes no else. If you want to choose between two values rather than keep or drop, the conditional goes in the expression at the front instead:
labels = ["even" if n % 2 == 0 else "odd" for n in nums]
Two different ifs, in two different places, doing two different jobs. Mixing them up is the most common comprehension error.
Nesting reads outer-first
[n for row in grid for n in row]
The clauses come in the same order as the nested loops would: for row outside, for n inside. It reads oddly because the expression sits before both, but the order after the expression is exactly the loop order.
One level of nesting is defensible. Two, plus a filter, is a line that will cost you a minute every time you come back to it — and the loop version costs nothing. The second program on this page puts both side by side and prints the same answer from each.
Comprehension or generator
Swap the brackets for round ones and you get a generator expression:
total = sum(n * n for n in range(10_000))
The comprehension builds the whole list first — every element in memory — then sums it. The generator produces one value at a time and never builds a list at all. When the result is consumed immediately by sum, any, max or a for, the generator is the better default, and the size difference is measurable: the page prints both.
The rule of thumb
Use a comprehension when it fits on one line and reads as a sentence. When you need a second for, a filter, and a conditional expression at once, write the loop. Comprehensions are for making simple transformations obvious, not for proving a loop can be compressed.