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

1 What You've Learned

ConceptOne-line reminder
Slicingseq[start:stop:step] — ranges, negatives, [::-1] reverses.
TruthinessEmpty/zero/None are falsy; and/or return operands; any()/all().
NoneAbsence of value; test with is None; the sentinel default fix.
Ternarya if cond else b — choose a value in one line.
Walrus:= assigns and returns; cleaner loops and reuse.
match/caseBranch on shape; literal, capture, wildcard _, guards.
Unpackinga, *rest = ...; swaps; *args/**kwargs; {**d1, **d2}.
Sortingsorted() 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:

# 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

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.