python · level 4

Collections & Comprehensions

list, dict, set, tuple — and the syntax that makes them sing.

125 XP

Collections & Comprehensions

The four core collections — list, dict, set, tuple — plus the syntax that turns most loops into one-liners.

list

Ordered, mutable, indexable.

xs = [1, 2, 3]
xs[0]                  # 1
xs[-1]                 # 3 (negative indexes count from the end)
xs[1:3]                # [2, 3] (slice)
xs.append(4)
xs.extend([5, 6])
xs.pop()               # remove + return last
xs.insert(0, 0)        # insert at index
xs.sort()
sorted(xs)             # returns NEW sorted list, doesn't mutate
xs.reverse()
len(xs)

Slicing also accepts a step: xs[::2] (every other), xs[::-1] (reversed copy).

dict

Key→value, fast lookup, ordered (insertion order, since 3.7).

d = {"name": "Alice", "age": 30}
d["name"]              # "Alice"
d.get("missing")       # None — no exception
d.get("missing", 0)    # 0 — fallback
d["email"] = "a@x.com"
del d["age"]
"name" in d            # True
d.keys() / d.values() / d.items()

Merge two dicts (3.9+): d3 = d1 | d2. Or unpack: {**d1, **d2}.

set

Unordered, unique, fast membership.

s = {1, 2, 3}
s.add(4)
s.discard(2)           # remove if present, no error if missing
3 in s                 # True
a | b                  # union
a & b                  # intersection
a - b                  # difference
a ^ b                  # symmetric difference

set() for an empty set — {} is an empty dict.

tuple

Like a list, but immutable. Used for fixed-size groups.

point = (10, 20)
x, y = point           # destructure
point[0]               # 10
point[0] = 99          # TypeError — tuples are immutable

Single-element tuple needs the trailing comma: (5,) is a tuple, (5) is just 5.

Comprehensions

The Python superpower. A list comprehension turns a for + if + append into one expression:

squares = [x * x for x in range(10)]
evens = [x for x in xs if x % 2 == 0]
flat = [x for row in matrix for x in row]      # nested

Dict and set comprehensions exist too:

char_counts = {ch: text.count(ch) for ch in set(text)}
unique_lower = {s.lower() for s in strings}

Generator expressions use () instead of [] and produce values lazily — no list is built:

total = sum(x * x for x in numbers)            # no intermediate list

When NOT to comprehension

If the comprehension has side effects (mutation, I/O, anything that's not building a value), write a regular loop. Comprehensions should be expressions, not procedures:

# Bad — comprehension used for the side effect.
[print(x) for x in xs]

# Good.
for x in xs:
    print(x)

defaultdict, Counter

The standard library has two collections that come up constantly:

from collections import defaultdict, Counter

# defaultdict — auto-creates the value when a key is missing.
groups = defaultdict(list)
for user in users:
    groups[user.team].append(user)

# Counter — multiset; tally occurrences.
counts = Counter(words)
counts.most_common(3)                          # [('the', 42), ...]

Big-O cheat sheet

Operation list dict set
Index / key lookup O(1) O(1) avg
x in coll O(n) O(1) avg O(1) avg
Append / add O(1) amortised O(1) avg O(1) avg
Insert at front O(n)
Sort O(n log n)

if x in some_list inside a loop is the most common O(n²) bug. Convert to a set first.