Reference · module 12
Comprehensions and sorting
Everything this module explains, on one page.
List comprehensions
Build a list in one line instead of four.
- [x * 2 for x in numbers] builds a new list by running x * 2 for every item. It is the loop from the third module — empty list, append, read after — written as one expression.
- Read it left to right in two halves: the for at the end says what it walks, and the piece at the front says what to make from each one. The result is a new list; the original is untouched.
- Use it when the line stays readable and the loop when it does not. A comprehension with two fors and a condition is shorter than a loop and harder to read than one, which is the wrong trade.
The mistake you are about to make
[print(x) for x in items]
for x in items: print(x)
A comprehension is shorter, so it starts replacing every loop. It builds a list — and with no result wanted you have built a list of None for a side effect.
Filtering
Keep only the items you want.
- [x for x in numbers if x > 0] keeps the items that pass and drops the rest. The if goes at the END, after the for, and it decides whether an item is included at all.
- So the result can be shorter than what went in, which is the difference from the last lesson. Filter nothing out and you get the same length; filter everything and you get [].
- Both halves work together: [x * 2 for x in numbers if x > 0] doubles only the positive ones. The if chooses, then the expression at the front transforms what survived.
The mistake you are about to make
[if x > 0 x for x in numbers]
[x for x in numbers if x > 0]
Said aloud the condition comes first. In a comprehension the if goes at the end, after the for, and decides whether the item gets in at all.
Sorting
Put a list in order, by whatever you choose.
- sorted(numbers) hands back a NEW list in order and leaves the original alone. numbers.sort() reorders the list in place and hands back nothing — the same split as append, and the same mistake waiting.
- sorted(numbers, reverse=True) turns it round. Strings sort alphabetically, and capitals come before lower case because that is where they sit in the character table — "Zoe" before "anna".
- key= says what to sort BY: sorted(words, key=len) orders by length. The function is named, not called — key=len, never key=len(). Python calls it once per item itself.
The mistake you are about to make
names = names.sort()
names.sort() or names = sorted(names)
Sort behaves like append: it reorders in place and returns None. Assigning it back throws the list away. The new-list version is sorted().
Dictionary comprehensions
Build a dictionary in one line, and turn one round.
- {w: len(w) for w in words} builds a dictionary. Same shape as a list comprehension with one difference: two expressions at the front, a key and a value, with a colon between them.
- Curly brackets rather than square, which is the only thing telling you what kind of thing is being built. A comprehension in square brackets is a list even if its expression looks like a pair.
- Walking a dictionary works too: {v: k for k, v in user.items()} swaps the keys and values round. Useful, and a trap — two keys with the same value collapse into one entry.
The mistake you are about to make
[w: len(w) for w in words]
{w: len(w) for w in words}
The brackets decide what gets built, not the expression inside. Square ones always make a list, so a colon in there is a syntax error.
Sets
Ask what is unique, and whether something is in a big collection.
- A set holds each value once and no more: set([1, 2, 2, 3]) is {1, 2, 3}. Adding something already there does nothing at all, and that is the whole feature.
- Which makes len(set(words)) the shortest honest answer to "how many different words are there". Wrapping a list in set() and counting is a whole algorithm in one line.
- A set has no order and cannot be indexed: my_set[0] is a TypeError. What it does instead is answer `in` almost instantly however large it is, which a list cannot.
The mistake you are about to make
my_set[0]
for x in my_set:
A set prints inside braces and looks like an ordered collection. It has neither order nor indexes: my_set[0] is a TypeError.