Checkpoint: Core Syntax
Reviewed & published by Brayan K
A checkpoint is a consolidation lesson that combines everything you've just learned — slicing, truthiness, None, ternaries, the walrus, match/case, unpacking, and sorting — into one realistic build.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
No new syntax here. Instead you'll recap the toolkit, write a small program that parses and ranks records using these features together, and check your understanding with a short quiz.
What This Checkpoint Covers
- Recap of all eight core-syntax lessons
- Combining slicing, unpacking, and sorting
- Classifying data with match/case
- A multi-step build challenge with a solution
- Guarding values with None and the ternary
- A checkpoint quiz to test recall
1 What You've Learned
| Concept | One-line reminder |
|---|---|
| Slicing | seq[start:stop:step] — ranges, negatives, [::-1] reverses. |
| Truthiness | Empty/zero/None are falsy; and/or return operands; any()/all(). |
| None | Absence of value; test with is None; the sentinel default fix. |
| Ternary | a if cond else b — choose a value in one line. |
| Walrus | := assigns and returns; cleaner loops and reuse. |
| match/case | Branch on shape; literal, capture, wildcard _, guards. |
| Unpacking | a, *rest = ...; swaps; *args/**kwargs; {**d1, **d2}. |
| Sorting | sorted() vs .sort(); key=; tuple keys; stable. |
🔥 Warm-Up: All Eight in One Script
Before the big challenge, here's a quick tour that fires each concept once. Read it, predict the output, then run it:
# A whirlwind tour of the toolkit
row = "Ada,88,math"
# Unpacking + slicing
name, score, *subjects = row.split(",")
print(name[::-1]) # adA (slicing/reverse)
# Truthiness + ternary
score = int(score)
status = "pass" if score >= 60 else "fail"
print(status) # pass
# None check
grade = None
print(grade is None) # True
# Walrus in a condition
if (n := len(name)) == 3:
print(f"3-letter name: {name}") # 3-letter name: Ada
# match/case
def kind(v):
match v:
case int():
return "number"
case str():
return "text"
case _:
return "other"
print(kind(score)) # number
# Sorting with a key
print(sorted(["bb", "a", "ccc"], key=len)) # ['a', 'bb', 'ccc']
# ✅ Expected output:
# adA
# pass
# True
# 3-letter name: Ada
# number
# ['a', 'bb', 'ccc']2 Build Challenge: Parse & Rank Records
You're given raw rows of player data. Build a small pipeline that:
- Parses each comma-separated row, using unpacking to split name from the scores.
- Classifies each player with match/case on their average: "gold" (90+), "silver" (75+), else "bronze".
- Sorts the results by average descending, breaking ties by name (a tuple key).
- Prints a ranked line per player, skipping any blank/empty row (truthiness).
# BUILD CHALLENGE starter - fill in the TODOs
rows = [
"Ada,90,88,95",
"Ben,70,75,80",
"", # blank row - skip it!
"Cleo,99,100,95",
"Dan,60,70,65",
]
def tier(avg):
match avg:
case a if a >= 90:
return "gold"
case a if a >= 75:
return "silver"
case _:
return "bronze"
players = []
for row in rows:
if not row: # truthiness: skip empty rows
continue
name, *scores = row.split(",") # unpacking
nums = [int(s) for s in scores]
avg = sum(nums) / len(nums)
players.append((name, avg, tier(avg)))
# TODO: sort by average DESC, then name ASC (tuple key)
ranked = sorted(players, key=lambda p: (-p[1], p[0]))
for rank, (name, avg, medal) in enumerate(ranked, start=1):
print(f"{rank}. {name} - {avg:.1f} ({medal})")
# Expected output:
# 1. Cleo - 98.0 (gold)
# 2. Ada - 91.0 (gold)
# 3. Ben - 75.0 (silver)
# 4. Dan - 65.0 (bronze)rows = [
"Ada,90,88,95",
"Ben,70,75,80",
"",
"Cleo,99,100,95",
"Dan,60,70,65",
]
def tier(avg):
# match on a guarded value to pick the medal
match avg:
case a if a >= 90:
return "gold"
case a if a >= 75:
return "silver"
case _:
return "bronze"
players = []
for row in rows:
if not row: # truthiness skips ""
continue
name, *scores = row.split(",") # unpacking: name + the rest
nums = [int(s) for s in scores] # comprehension
avg = sum(nums) / len(nums)
players.append((name, avg, tier(avg)))
# tuple key: -avg for descending, name for the A-Z tie-break (stable)
ranked = sorted(players, key=lambda p: (-p[1], p[0]))
for rank, (name, avg, medal) in enumerate(ranked, start=1):
print(f"{rank}. {name} - {avg:.1f} ({medal})")
# 1. Cleo - 98.0 (gold)
# 2. Ada - 91.0 (gold)
# 3. Ben - 75.0 (silver)
# 4. Dan - 65.0 (bronze)📝 Checkpoint Quiz
Answer each from memory, then expand to check. A wrong answer points you to the lesson to revisit.
1. What does "python"[::-1] produce, and what does [::-1] mean?
'nohtyp'. A step of -1 with both bounds omitted returns a reversed copy of the whole sequence. (Lesson: Slicing)
2. Which of these are falsy: 0, "0", [], [0], None?
0, [], and None are falsy. "0" (non-empty string) and [0] (non-empty list) are truthy. (Lesson: Booleans & Truthiness)
3. Why prefer x is None over x == None?
None is a unique singleton, so identity (is) is correct, fast, and can't be fooled by a class that overrides ==. It's the PEP 8 recommendation. (Lesson: None & NoneType)
4. Rewrite this as a ternary: if t >= 25: label = "hot" else: label = "mild".
label = "hot" if t >= 25 else "mild" — value first, condition, then fallback. (Lesson: Ternary)
5. In first, *rest = [1, 2, 3, 4], what is rest and what type is it?
rest is [2, 3, 4], and a starred target is always a list (even from a tuple). (Lesson: Unpacking)
6. How do you sort records by score descending, then name ascending?
Use a tuple key that negates the number: sorted(items, key=lambda p: (-p.score, p.name)). Python's stable sort keeps the tie-break order. (Lesson: Sorting)
Frequently Asked Questions
Checkpoint cleared — your core syntax is solid!
You combined slicing, truthiness, None, ternaries, the walrus, match/case, unpacking, and sorting into a working pipeline, and proved your recall on the quiz. This toolkit is the backbone of everyday Python.
Practice quiz
What does "python"[::-1] produce?
- "python"
- "nohty"
- "nohtyp"
- an error
Answer: "nohtyp". A slice with step -1 and both bounds omitted returns a reversed copy of the whole sequence, so "python" becomes "nohtyp".
Which of these values is truthy?
- "0"
- 0
- []
- None
Answer: "0". The string "0" is non-empty, so it is truthy. 0, [] (empty list), and None are all falsy.
Why prefer x is None over x == None?
- is None is shorter to type
- == None raises a SyntaxError
- They behave differently for integers only
- None is a unique singleton, so identity is correct, fast, and cannot be fooled by a custom __eq__
Answer: None is a unique singleton, so identity is correct, fast, and cannot be fooled by a custom __eq__. None is a single, unique object, so the identity check is is None is the correct and PEP 8 recommended way to test for it.
What is the ternary form of: if t >= 25: label = "hot" else: label = "mild"?
- label = if t >= 25 "hot" else "mild"
- label = "hot" if t >= 25 else "mild"
- label = t >= 25 ? "hot" : "mild"
- label = "mild" if t >= 25 else "hot"
Answer: label = "hot" if t >= 25 else "mild". Python's conditional expression puts the value first: value_if_true if condition else value_if_false.
In first, *rest = [1, 2, 3, 4], what is rest?
- [2, 3, 4]
- (2, 3, 4)
- [1, 2, 3]
- 4
Answer: [2, 3, 4]. A starred target captures the remaining items, and it is always a list — here [2, 3, 4] — even when unpacking a tuple.
What does the walrus operator := do?
- Compares two values for equality
- Defines a lambda
- Assigns a value and returns it as part of an expression
- Performs floor division
Answer: Assigns a value and returns it as part of an expression. The walrus operator assigns to a name and also returns the value, letting you assign inside conditions and comprehensions.
In a match statement, what does the case _ pattern do?
- Matches only the value None
- Acts as a wildcard that matches anything (the default branch)
- Matches an empty sequence
- Raises an error if reached
Answer: Acts as a wildcard that matches anything (the default branch). The underscore is the wildcard pattern: it matches any value and is typically the final, catch-all case.
How do you sort records by score descending, then name ascending?
- sorted(items, key=lambda p: (p.score, p.name))
- sorted(items, reverse=True)
- sorted(items, key=lambda p: p.name, reverse=True)
- sorted(items, key=lambda p: (-p.score, p.name))
Answer: sorted(items, key=lambda p: (-p.score, p.name)). Negating the number makes it sort descending while name stays ascending; the tuple key combines both, and the sort is stable.
What is the difference between sorted(x) and x.sort()?
- They are identical in every way
- sorted() returns a new list; .sort() sorts the list in place and returns None
- .sort() returns a new list; sorted() mutates in place
- sorted() only works on tuples
Answer: sorted() returns a new list; .sort() sorts the list in place and returns None. sorted() builds and returns a new sorted list, leaving the original untouched, while list.sort() reorders the list in place and returns None.
What does the expression "" or "default" evaluate to?
- ""
- True
- "default"
- None
Answer: "default". or returns the first truthy operand; "" is falsy, so the expression yields the second operand, "default".
Continue this course
- Previous: Sorting with sorted() & key
- Next: functools: lru_cache, partial, reduce — Memoize with lru_cache, pre-fill args with partial, and fold with reduce
- Quick reference: Python cheat sheet
Frequently asked questions
What is this checkpoint for?
It's a consolidation stop. Rather than introducing new syntax, it asks you to combine the recent lessons — slicing, truthiness, None, the ternary, the walrus, match/case, unpacking, and sorting — into one realistic task. Building something end-to-end is how these tools move from 'I've seen it' to 'I reach for it automatically'.
How should I approach the build challenge?
Start with the starter code and run it to see the shape of the data. Then tackle one transformation at a time: parse each record, classify it with match/case, unpack the fields you need, and finally sort the results with a key. Run it after each step. The full solution is hidden in a details block so you can check yourself only after a real attempt.
What should I review if I get stuck?
Match the part you're stuck on to its lesson. Trouble pulling fields apart? Revisit Unpacking. Unsure how to order results? Revisit Sorting with key. Confused by a None result? Revisit None & NoneType. Each checkpoint quiz answer also names the concept, so a wrong answer points you straight to the lesson to reread.
Do I need to memorize all of this?
No — aim for recognition and recall, not memorization. The goal is that when you see a task like 'order these records' or 'split this row', the right tool comes to mind. Working programmers look things up constantly; what matters is knowing which tool fits, which is exactly what this checkpoint rehearses.