What’s one thing you learned? What’s still confusing?
Mini-Project: Grade Statistics
Compute a class report (mean, min, max, pass rate, top scorers) using list comprehensions.
Dictionaries & Hash Tables: O(1) Lookup Explained
Python dicts: hash mechanics, collision resolution, all dict methods, and comprehensions.
Mini-Project: Word Counter
Build a word-frequency counter — the foundation of every NLP pipeline.
Interactive Labs for This Track
Loop Visualizer
You're a factory robot repeating the same task on an assembly line — watch how loops automate repetitive work
List Slicing
You have a playlist of 50 songs — grab just tracks 10 through 20 with a single slice expression
Sorting Algorithms
You're organizing a library of 10,000 books — which sorting method is fastest?
Ask questions, share insights
[token for token in tokens if token.strip()] on the first screen. They're 2-3× faster than equivalent for-loops because CPython optimizes the bytecode.You often write for loops just to build a new list:
# The verbose way — 4 lines to do one thing
squares = []
for x in range(10):
squares.append(x ** 2)
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]Python has a one-line way to express this:
# The Pythonic way — 1 line, same result
squares = [x ** 2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]What does [x * 2 for x in range(4)] produce?
range(4) gives 0, 1, 2, 3 (NOT 1, 2, 3, 4 — range starts at 0 and excludes the end). The comprehension doubles each: 0*2, 1*2, 2*2, 3*2. Two beginner traps in one expression: range(4) doesn't include 4 (excludes the stop value), and it starts at 0 (not 1). Once these become reflexes, comprehensions feel natural.x flowing left-to-right: pointer lands on the input, the filter gate drops failing items (red ✗) or lets passers through (green ✓), the transform bubble converts the value, and survivors land in the output on the right. Side-by-side, the equivalent for-loop highlights the matching line at every step — so you can see the line result.append(x*2) light up the moment an item flies into the output list. Six presets cover the full vocabulary: filter+transform, tuples, strings, nested cartesian, set dedup, and dict comprehensions.# [expression for item in iterable]
names = ["alice", "bob", "charlie"]
upper = [name.upper() for name in names]
# ["ALICE", "BOB", "CHARLIE"]
lengths = [len(name) for name in names]
# [5, 3, 7]
doubled = [x * 2 for x in [1, 2, 3, 4, 5]]
# [2, 4, 6, 8, 10]Hit aNameErrorinside a comprehension? Typos in the iterable name or the loop variable are the usual cause ([n for nme in names]raisesNameError: name 'nme' is not definedwhen used). See the error decoder.
# [expression for item in iterable if condition]
numbers = range(20)
evens = [x for x in numbers if x % 2 == 0]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
long_names = [name for name in names if len(name) > 4]
# ["alice", "charlie"]
positive_nums = [x for x in [-3, -1, 0, 2, 5, -2, 8] if x > 0]
# [2, 5, 8]What does [x ** 2 for x in [1, 2, 3, 4] if x % 2 == 0] produce?
if filter runs FIRST: only 2 and 4 pass x % 2 == 0. Then the expression x ** 2 is applied to each: 2**2 = 4, 4**2 = 16. The order matters conceptually: think of it as "from these items, keep the ones that pass the filter, then transform them." The filter is the gate, the expression is the factory. Common misconception: thinking the expression runs first and then filters — it doesn't.Which comprehension keeps only the even numbers from `[1, 2, 3, 4]`?
# Square only the even numbers
even_squares = [x ** 2 for x in range(10) if x % 2 == 0]
# [0, 4, 16, 36, 64]
# Clean text — lowercase and strip spaces, skip empty strings
raw = [" Hello ", "WORLD", "", " Python ", ""]
clean = [s.lower().strip() for s in raw if s.strip()]
# ["hello", "world", "python"]Same pattern — but creates a dictionary instead of a list:
# {key: value for item in iterable}
words = ["apple", "banana", "cherry"]
word_lengths = {word: len(word) for word in words}
# {"apple": 5, "banana": 6, "cherry": 6}
# Flip a dictionary (swap keys and values)
original = {"a": 1, "b": 2, "c": 3}
flipped = {v: k for k, v in original.items()}
# {1: "a", 2: "b", 3: "c"}
# Square numbers 1-5 as a lookup dict
squares_dict = {x: x**2 for x in range(1, 6)}
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}What does `{n: n*10 for n in [1, 2, 3]}` produce?
What is the type of result? result = {x for x in [1, 2, 2, 3, 3, 3]}
{1, 2, 3}. Curly braces {} with a single expression (no key: value pair) create a SET comprehension, not a dict. Sets automatically deduplicate, so the repeated 2s and 3s collapse to one each. This is the most common idiom for "get unique values": {item for item in collection}. The catch: {} alone (empty braces) is an empty DICT, not an empty set — use set() for an empty set.Creates a set — unique values only:
# {expression for item in iterable}
words = ["apple", "banana", "apple", "cherry", "banana"]
unique_lengths = {len(word) for word in words}
# {5, 6} — only unique lengths (apple=5, banana=6, cherry=6)
# All unique first letters
first_letters = {word[0] for word in words}
# {"a", "b", "c"}import os
# Load all .csv files from a directory
csv_files = [f for f in os.listdir("data/") if f.endswith(".csv")]
# Normalize a list of values to 0–1 range
raw_scores = [45, 78, 23, 91, 56]
min_s, max_s = min(raw_scores), max(raw_scores)
normalized = [(x - min_s) / (max_s - min_s) for x in raw_scores]
# Filter training examples where label is valid
dataset = [{"text": "...", "label": 1}, {"text": "...", "label": -1}, ...]
valid = [item for item in dataset if item["label"] in {0, 1}]
# Extract just the labels
labels = [item["label"] for item in valid]Comprehensions shine when the logic is simple. When it gets complex, a for loop is better:
# ❌ Too hard to read — nested comprehension
matrix = [[1 if row == col else 0 for col in range(3)] for row in range(3)]
# ✅ Clearer with a for loop
matrix = []
for row in range(3):
matrix.append([1 if row == col else 0 for col in range(3)])
# Rule of thumb: if you can't read the comprehension in 5 seconds, use a loopInteractive Lab
Practice working with lists and transformations interactively
What does [x for x in range(10) if x % 3 == 0] produce?
This comprehension is supposed to keep only the even numbers, but it crashes with a SyntaxError. Fix the condition.
[2, 4, 6, 8]
You are given a list of (name, grade) tuples. Write a function `passing(grades)` that returns a list of (name, grade) for every student whose grade is at least 60. Use a single list comprehension.
>>> passing([("Alice", 92), ("Bob", 45), ("Cara", 78), ("Dan", 59)])
[('Alice', 92), ('Cara', 78)]def passing(grades):
# TODO: return [(name, grade), ...] for students with grade >= 60
pass
print(passing([("Alice", 92), ("Bob", 45), ("Cara", 78), ("Dan", 59)]))