Python has no switch statement, and for most of its history the answer was use a dictionary or a chain of if/elif. Since Python 3.10 there is match, which looks like a switch but is actually structural pattern matching - it can destructure tuples, match against types, bind variables, and guard with conditions, which a C-style switch cannot. So the real answer is: for simple value dispatch, a dict is often cleanest; for anything with structure, match is more powerful than the switch you were missing.
Table of contents
- The dictionary dispatch approach
- if-elif-else, the honest fallback
- The match statement, from Python 3.10
- Where match earns its keep: structure
- Which to reach for
- How this fits the rest of the stack
- FAQ
The dictionary dispatch approach
Before match, and still often the cleanest option, a dictionary maps values to results or functions:
def handle(command):
actions = {
"start": start_server,
"stop": stop_server,
"status": show_status,
}
action = actions.get(command, unknown_command)
return action()
The dict maps each case to a function; .get(command, default) handles the else case. This is genuinely elegant for value dispatch - it is a lookup table, it is O(1), and adding a case is one line.
For mapping a value to a value rather than an action, it is even simpler:
day_type = {0: "weekday", 6: "weekend"}.get(day, "weekday")
When your switch is really just this value maps to that value, a dict is clearer than any switch statement in any language. Reach for it first before assuming you need match.
if-elif-else, the honest fallback
When cases involve ranges or conditions rather than exact values, a plain if/elif/else chain is fine and readable:
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"
There is no shame in this. A switch statement in other languages cannot do >= 90 cleanly anyway - it matches exact values - so for range logic, if/elif is what you would reach for even in a language that has switch.
The chain reads top to bottom, the first true branch wins, and else catches the rest. It is the right tool whenever the cases are conditions, not constants. Do not contort a dict or a match to avoid an honest if/elif when the logic is genuinely a series of tests.
The match statement, from Python 3.10
match looks switch-like for simple values:
def http_label(status):
match status:
case 200:
return "OK"
case 404:
return "Not Found"
case 500 | 502 | 503: # multiple values with |
return "Server Error"
case _: # the wildcard, like default
return "Unknown"
case _ is the catch-all default. | combines values in one case. There is no fall-through - each case is self-contained, so you never need C’s break, and you never get C’s accidental fall-through bug either.
For plain value dispatch this is readable, but honestly a dict often does the same job in less space. The reason match exists is not this - it is the structural matching in the next section, which is a genuinely different capability.
Where match earns its keep: structure
match is structural pattern matching, and this is what a switch statement cannot do. It can destructure and match shapes:
def describe(point):
match point:
case (0, 0):
return "origin"
case (0, y):
return f"on the y-axis at {y}" # binds y
case (x, 0):
return f"on the x-axis at {x}" # binds x
case (x, y):
return f"at ({x}, {y})"
case _:
return "not a point"
It matches the shape of the data and binds variables from it in one step. It works on classes too, matching attributes, and supports guards:
case Point(x=x, y=y) if x == y:
return "on the diagonal"
This is dispatch on the structure and content of data, not just on a single value. For parsing, for handling different message shapes, for anything where you branch on what a piece of data looks like, match is far beyond what a switch could offer - which is why comparing it to switch undersells it.
Which to reach for
A short guide:
- Value maps to value - a dictionary.
{"a": 1}.get(key, default). - Value maps to an action - a dictionary of functions. Clean and extensible.
- Ranges or conditions -
if/elif/else. Honest and readable. - Matching on the shape or type of data -
match. This is its home turf. - Simple exact-value dispatch on 3.10+ - either a dict or
match; pick whichever reads better to you.
The mistake is treating match as the switch Python was missing and reaching for it everywhere. For value lookup, a dict is usually tighter. match shines when you are branching on structure - tuples, class attributes, nested shapes - and that is the case worth reaching for it. Match the tool to the shape of the decision, and Python’s lack of a switch stops feeling like a gap at all.
How this fits the rest of the stack
Choosing the right dispatch mechanism - a dict, an if-chain, or structural matching - is a readability decision that compounds across a codebase. When that code becomes a request handler routing on message type or status, clean dispatch is the difference between a handler you can extend in one line and one you dread touching. The RunxBuild hosting calculator lays out the service, database, storage, and bandwidth as separate line items, and the RunxBuild dashboard is where the team watches deploys, logs, and restarts as they happen.
Useful related references:
- Ubuntu Desktop Managers: Which One to Pick, What to Skip, How to Switch
- Private Methods in Python: There Are None, and That Is Fine
- Null in Python: There Is No null, There Is None - and That Distinction Matters
- Python services on RunxBuild
FAQ
Does Python have a switch statement?
No. Python has no switch. For simple value dispatch, use a dictionary; for ranges and conditions, use if/elif/else; and from Python 3.10 onward, use the match statement, which does structural pattern matching that goes well beyond a traditional switch.
How do I write a switch case in Python?
The cleanest option for value dispatch is a dictionary: map each case to a value or function and use .get(key, default) for the else case. On Python 3.10+ you can use match/case with case _ as the default, but a dict is often tighter for exact-value dispatch.
What is the match statement in Python?
Introduced in Python 3.10, match compares a value against case patterns. It looks switch-like for simple values but is actually structural pattern matching - it can destructure tuples, match class attributes, bind variables, and use guard conditions, with no fall-through between cases.
When should I use match instead of a dictionary?
Use match when you branch on the shape or type of data - tuples, class attributes, nested structures - because it destructures and binds variables in one step. For plain value-to-value or value-to-action dispatch, a dictionary is usually cleaner and shorter.
Does Python’s match have fall-through like C’s switch?
No. Each case in a match is self-contained, so execution never falls through to the next case, and you never need a break. To match several values in one case, combine them with |, as in case 500 | 502 | 503.