Lesson 12 · 12 of 20
Enums and match/case · Python
Order states with Enum and events handled with match/case in Python: value, mapping and sequence patterns, captures and guards.

An enumeration (Enum) groups a closed set of named values. Status.PAID is much safer than the string "paid": a typo such as Status.PIAD fails straight away. Each member has a name and a value, you can loop over them with for status in Status, and you can look one up by value with Status("paid"). The first loop prints each member with !s (which gives Status.PAID) and its value with !r.
`match` compares a value against a series of patterns and runs the first case that fits. In next_step, case Status.PENDING: compares against a specific member, and `case _:` catches everything else, like an else.
In handle, the patterns describe the shape of the data. {"type": "order", "id": oid, ...} matches any dictionary with those keys (even if it has more) and captures the values into oid and total. The if total >= 100 part is a guard: if it fails, the next case is tried, and that is the one that accepts order 8.
("refund", oid, amount) matches any three-item sequence starting with "refund" (tuple or list; strings do not count). ["cancel", *ids] accepts any length and collects the rest into the list ids.
The last event, "ping", matches nothing and falls into case _. {event!r} prints it with repr(), quotes included.
Code · main.py
from enum import Enumclass Status(Enum): PENDING = "pending" PAID = "paid" SHIPPED = "shipped"def next_step(status): match status: case Status.PENDING: return "wait for payment" case Status.PAID: return "pack and ship" case _: # anything else return "nothing to do"def handle(event): match event: # match by shape and capture values case {"type": "order", "id": oid, "total": total} if total >= 100: return f"order {oid}: big order, check stock" case {"type": "order", "id": oid}: return f"order {oid}: accepted" case ("refund", oid, amount): return f"refund {amount} EUR for order {oid}" case ["cancel", *ids]: return f"cancel {len(ids)} orders: {ids}" case _: return f"unknown event: {event!r}"for status in Status: print(f"{status!s:<15} {status.value!r:<10} -> {next_step(status)}")for event in [{"type": "order", "id": 7, "total": 250}, {"type": "order", "id": 8}, ("refund", 7, 40), ["cancel", 3, 4], "ping"]: print(handle(event))Output · python3 main.py
Status.PENDING 'pending' -> wait for payment Status.PAID 'paid' -> pack and ship Status.SHIPPED 'shipped' -> nothing to do order 7: big order, check stock order 8: accepted refund 40 EUR for order 7 cancel 2 orders: [3, 4] unknown event: 'ping'
Key points
Enumgives fixed names to a closed set of values.matchtries eachcasein order and runs the first one that fits.- Patterns can capture values into variables.
- An
ifafter the pattern adds a condition (a guard). case _:catches whatever did not match.
Exercise
Add a CANCELLED state to Status and a case in next_step that returns "refund the customer"; then make refund events with a negative amount print a warning.