Filter in a comprehension, or use a loop
An `if` at the end of a comprehension keeps only the items that pass. Knowing when a plain loop reads better is part of using comprehensions well.
- Filter with
[value for item in items if test], in lists, dictionaries and sets - Tell the filter
ifat the end from the conditional expression in front - Choose a loop for side effects, early exits and running state
The the Collection Algorithms module filter loop had an if around the append. In a comprehension the same test goes at the end: [value for item in items if test]. Items that fail the test produce nothing, so the result can be shorter than the input. The same clause works in dictionary and set comprehensions.
Run each example to see what it prints. Running examples doesn't count toward progress.
flights = [
{"flight": "UA2017", "arrival_delay": -4},
{"flight": "MQ3443", "arrival_delay": 12},
{"flight": "MQ3615", "arrival_delay": 42},
{"flight": "DL1270", "arrival_delay": -25},
{"flight": "AA1214", "arrival_delay": 16},
]
late = [f["flight"] for f in flights if f["arrival_delay"] >= 15]
print(late)
delays = {f["flight"]: f["arrival_delay"] for f in flights if f["arrival_delay"] >= 15}
print(delays)Two ifs can appear in a comprehension and they do different jobs. A conditional expression in front (“Build a list with a comprehension”) chooses a value, and every item still produces one. An if at the end decides whether the item produces anything at all.
delays = [-4, 12, 42, -25, 16] early_as_zero = [d if d > 0 else 0 for d in delays] only_late = [d for d in delays if d > 0] print(early_as_zero) print(only_late)
delays = [-4, 12, 42] late = [d for d in delays if d > 0 else 0] print(late)
An if may also follow the first for of a two-clause comprehension, to skip whole groups before the inner loop runs: [sku for o in orders if o["paid"] for sku in o["skus"]].
When a loop is clearer. A comprehension says *build this collection*. Use a plain for loop when the job is something else:
- side effects: printing, writing a file, appending to another list;
- stopping early:
breakat the first match; - state that carries over: a running balance or a previous value, because each item of a comprehension is computed on its own;
- several steps per item: if the expression needs three method calls and two conditions, give the steps names in a loop.
A good rule: one transform and one filter fit in a comprehension; more than that belongs in a loop or a helper function.
[value for item in items if test]keeps only items that pass; the result can be shorter than the input.- In front,
a if test else bchooses a value; at the end,if testfilters. A filter has noelse. - Use a loop for printing, stopping early, running totals, and anything that needs several named steps.
- Next module: built-in functions such as
zip,sortedwith a key,any,all,sum,minandmax.