Question bank — Built-in functions — map, filter, zip, enumerate, sorted, reversed, min, max, sum, any, all
First — the tiny vocabulary every trap uses
The questions below use short variable names on purpose (that is how real Python is written). Here is what each one means before you meet it in a trap — no prior Python idiom assumed:
Three behaviour families — the visual taxonomy
Every one of the 11 built-ins falls into exactly one of three buckets. The figure below is the whole page in one picture — glance at it, then the traps will feel like variations on these three shapes.


True or false — justify
map(f, xs) returns a list.
list(...). Printing it raw shows <map object ...>.sorted(xs) changes the original list xs.
sorted is the photocopier: it builds and returns a new list; the original is untouched. It is xs.sort() that scribbles on the original in place.all([]) is True.
all is AND over the items, and AND's identity element is True, so "every one of zero items is truthy" is vacuously satisfied.any([]) is True.
False; any is OR over the items, and OR's identity element is False, so with nothing to make it true it stays false.filter(None, xs) removes the None values from xs.
None as the predicate drops every falsy item (0, '', [], None, False), not only None.zip(a, b) raises an error when a and b have different lengths.
zip pulls ONE item from a, then ONE from b, in a loop; the moment either runs dry it stops the whole loop, so the shorter one dictates the length and the leftover items of the longer are never pulled.enumerate(xs) always starts counting at 1.
0 by default; you pass start=1 explicitly if you want 1-based indexing.reversed(xs) works on any iterable.
reversed on it raises TypeError.sum(['a', 'b']) gives 'ab'.
sum starts its accumulator at the number 0, so the very first step 0 + 'a' raises TypeError. Use ''.join(...) for strings.You can loop over the same map object twice and get the same result both times.
map object is a single-use conveyor belt; the first full pass exhausts it, and the second pass yields nothing. (See the lifecycle figure below.)max and min on an empty list return 0.
ValueError on an empty iterable (there is no element to return). Supply a default= argument to avoid the error.sorted is guaranteed to keep equal-key items in their original relative order.
Spot the error
Each item below shows the buggy line, then a mini step-by-step trace of how it goes wrong, then the fix.
xs = xs.sort() — what breaks?
xs.sort() sorts xs in place and returns None → None is assigned back to xs → xs is now None, not a list. Fix: xs = sorted(xs), or call xs.sort() on its own line and don't assign it.print(map(str, [1,2,3])) — why not the numbers?
map(...) builds the conveyor belt object but pulls nothing off it → print shows the object itself → output <map object at 0x...>. Fix: print(list(map(str, [1,2,3]))) forces the belt to run and collects ['1','2','3'].sorted(xs, key=lambda x: x > 5) to keep only items above 5 — what's wrong?
key maps each x to True/False (its comparison rank), it never drops anything → items with key False sort before key True, so nothing is removed. Fix: use filter(lambda x: x > 5, xs) (or a comprehension) to actually remove items.m = map(int, data); list(m); list(m) gives [] the second time — why?
list(m) walks the belt end-to-end → belt now empty → line 3 list(m) finds nothing left → []. Fix: materialize once — m = list(map(int, data)) — then reuse the list as many times as you like.max(people, key=len) where people = [('Ann',30),('Bo',25)] to find the oldest — bug?
len(('Ann',30)) is 2 and len(('Bo',25)) is also 2 → every item ties → max returns the first tied item, ('Ann',30), not the oldest. Fix: key=lambda p: p[1] to compare by the age field.total = sum(map(square, nums)); avg = total / len(map(square, nums)) — why does len fail?
len needs to know a count up front, but a map object never computes its length → Python raises TypeError: object of type 'map' has no len(). Fix: avg = total / len(nums) (the input list does have a length), or build a list first.for i in range(len(xs)): print(i, xs[i]) — what's the cleaner, safer form?
for i, v in enumerate(xs): print(i, v) — no index math, no chance of an off-by-one or IndexError, and it works on any iterable without needing [i].nums, letters = zip(pairs) to unzip [(1,'a'),(2,'b')] — why one column only?
* you passed ONE argument, so zip iterates pairs itself and tries to unpack its two tuples into nums, letters → not the transpose you wanted. Fix: zip(*pairs) spreads the pairs into separate arguments so it pairs column-wise → (1,2) and ('a','b').Why questions
Why is map lazy instead of eagerly building a list?
sum/any without ever materializing the whole sequence.Why does any stop as soon as it hits a truthy item?
all stops at the first falsy item.Why prefer sorted(xs) over xs.sort() sometimes?
sorted returns a value while leaving the original intact, so you can keep the unsorted data and the sorted view. .sort() destroys the original ordering.Why does filter(None, xs) exist as a shortcut?
None says "use each item's own truthiness as the predicate" — using exactly the falsy list from the truthiness figure above.Why does sum take a start argument?
start is the initial accumulator value, letting you offset the total (sum(xs, 100)) or set a different starting point when accumulating — though for strings you should still use join (starting at 0 clashes with text).Why does enumerate beat a separate counter variable you increment yourself?
Why does key receive one item at a time rather than the whole list?
key(item) is that per-item projection.Edge cases
What does list(zip()) (no arguments) give?
[] — with nothing to pair, there are zero tuples to produce.What does all([0]) return, and why not all counting length?
False — all tests truthiness, and 0 is falsy; the list is non-empty but its single item fails the test.What does any([[], '', 0]) return?
False — every item is falsy (empty list, empty string, zero), so no item makes the OR true.What does sum([]) return?
0 — the default start accumulator, since adding nothing to the initial 0 leaves 0.What does max([], default=-1) return?
-1 — with default supplied, an empty iterable yields that fallback instead of raising ValueError.What does min([], default=99) return, and how does it differ from min([])?
99 — min accepts the same default= escape hatch as max; without it, min([]) raises ValueError for the identical "no element to return" reason.What happens with min([3, 3, 3], key=abs) when all keys tie?
sorted).What does list(map(lambda a, b: a+b, [1,2,3], [10,20])) give?
[11, 22] — with multiple iterables map stops at the shortest, exactly like zip, so the trailing 3 is dropped.What does list(reversed(range(3))) give, and why is range allowed?
[2, 1, 0] — range is a proper sequence with a known length and indexing, so reversed can walk it back-to-front without materializing it first.The exhaustion lifecycle — see it once, never forget it
The single most common trap is reusing a lazy iterator. The figure traces a map object across two list(...) calls so you can see the belt empty out.

Recall One-line rule to survive every trap
Ask three questions of any built-in call: Is it lazy? (conveyor belt — wrap in list, use once), Does it mutate or return? (sorted returns a copy, .sort() scribbles on the original), Does it test truthiness? (filter/any/all follow the falsy list: 0 '' [] {} () None False).