Question
Python Switch Statement Alternatives: Dictionary Dispatch, if/elif, and match
Question
How can I write a Python function that returns different fixed values according to an input index? In languages with switch or case statements, I would use one of those constructs. What are the recommended Python approaches for this situation?
Short Answer
Python has several clear alternatives to a traditional switch statement. By the end of this page, you will know when to use a dictionary lookup for fixed mappings, if/elif for conditions, and match/case in Python 3.10 and later.
Concept
A switch statement selects one outcome from several alternatives based on a value. Python historically did not have a switch keyword, so Python code commonly expresses the same idea with other language features.
For a value that maps directly to a fixed result, a dictionary is usually the most concise and maintainable choice. A dictionary stores key-value pairs, so an input index can be used as a key.
labels = {
1: "first",
2: "second",
3: "third",
}
result = labels[2] # "second"
Python 3.10 introduced match/case, called structural pattern matching. It can look similar to a switch statement, and it is especially useful when cases involve shapes of data, such as lists, dictionaries, or classes. For a simple fixed lookup, however, a dictionary is often simpler.
if/elif remains the right tool when each branch depends on a comparison or condition rather than exact values. For example, checking whether a score is greater than 90 cannot be represented as a direct dictionary lookup.
Choosing the clearest construct matters because it makes adding cases, handling invalid input, and reviewing code easier.
Mental Model
Think of a dictionary as a labelled set of drawers.
- The input index is the label you look for.
- The associated value is the item inside that drawer.
- If a drawer does not exist, you decide whether to use a default item or report an error.
messages = {"en": "Hello", "fr": "Bonjour"}
Looking up messages["fr"] means: “Open the drawer labelled fr.”
By contrast, an if/elif chain is like asking a sequence of yes-or-no questions until one answer is yes. match/case is like sorting an item into a labelled category, including categories based on its structure.
Syntax and Examples
For a direct mapping from one exact value to another, use a dictionary.
def weekday_name(index):
names = {
0: "Monday",
1: "Tuesday",
2: "Wednesday",
3: "Thursday",
4: "Friday",
}
return names.get(index, "Unknown day")
print(weekday_name(2)) # Wednesday
print(weekday_name(9)) # Unknown day
dict.get(key, default) returns the matching value when key exists. Otherwise, it returns the supplied default.
For a small set of condition-based branches, use if/elif.
def score_band(score):
if score >= 90:
return "excellent"
elif score >= :
Step by Step Execution
Consider this dictionary-based function:
def shipping_cost(zone):
costs = {
"local": 5,
"national": 12,
"international": 25,
}
return costs.get(zone, 0)
price = shipping_cost("national")
Step by step:
- Python calls
shipping_costwithzoneset to"national". - The
costsdictionary is created with three keys. costs.get("national", 0)searches for the key"national".- The key exists, so the lookup produces
12. - The function returns
12. priceis assigned the value12.
If the call were shipping_cost("moon"), the key would not exist and .get(zone, 0) would return the default value .
Real World Use Cases
Dictionary lookups and related branching patterns appear in many applications:
- Status labels: Map numeric or string status codes to display text.
status_labels = {200: "OK", 404: "Not Found", 500: "Server Error"} - Configuration: Select a URL, file path, or setting for an environment such as
"development"or"production". - Formatting: Map a currency code to its symbol or decimal precision.
- Command-line tools: Map a command name to the function that handles it.
- APIs: Convert known request types into response handlers.
- Data processing: Categorize known input values before writing reports or importing records.
Use if/elif for value ranges and combined conditions, such as permissions, account balances, or score thresholds. Use match when the decision depends on the form of structured input.
Real Codebase Usage
In production code, developers usually choose the smallest clear construct for the decision.
Fixed values: dictionary lookup
Keep mappings close to configuration or constants, rather than burying them inside a long function.
ROLE_LABELS = {
"admin": "Administrator",
"editor": "Content editor",
"viewer": "Read-only user",
}
def role_label(role):
return ROLE_LABELS.get(role, "Unknown role")
Actions: dictionary dispatch
A dictionary can map values to functions instead of fixed values.
def create_user():
return "Creating user"
def delete_user():
return "Deleting user"
ACTIONS = {
"create": create_user,
"delete": delete_user,
}
def run_action(name):
action = ACTIONS.get(name)
if action is None:
raise ValueError(f"Unsupported action: {name}")
action()
Common Mistakes
Assuming Python has no switch-like syntax at all
Python 3.10+ has match/case, but it is not always the best replacement. For a simple key-to-value mapping, a dictionary is often shorter.
Using dictionary indexing when unknown input is normal
This raises KeyError if the key is missing:
colors = {1: "red", 2: "blue"}
print(colors[3]) # KeyError
Use .get() when a fallback is appropriate:
print(colors.get(3, "unknown"))
Hiding invalid input with an unsafe default
A default can conceal a bug if an unsupported value should never occur. Raise an error or validate instead.
modes = {"read": "r", "write": "w"}
mode = modes.get("delete", "r") # Silently chooses read mode
For this situation, explicit validation is safer.
Comparisons
| Approach | Best for | Example | Notes |
|---|---|---|---|
| Dictionary lookup | Exact input mapped to fixed data | {1: "one", 2: "two"} | Concise and easy to extend. |
| Dictionary dispatch | Exact input mapped to an action | {"add": add_item} | Store function objects, then call the selected one. |
if/elif/else | Ranges or complex boolean conditions | if age >= 18: | Best when conditions are not simple equality checks. |
match/case | Exact values or structured patterns |
Cheat Sheet
# Fixed mapping with a safe fallback
value = mapping.get(key, default)
# Fixed mapping where a missing key is an error
value = mapping[key] # raises KeyError if absent
# Conditional branching
if condition:
...
elif other_condition:
...
else:
...
# Python 3.10+ matching
match value:
case "known":
...
case _:
...
# Function dispatch
handlers = {"save": save_file, "load": load_file}
handler = handlers.get(command)
if handler is None:
raise ValueError("Unknown command")
result = handler()
- Use a dictionary for exact key-to-value mappings.
- Use
.get(key, default)only if a fallback is valid. - Use
mapping[key]when missing keys should fail loudly. - Use
if/eliffor comparisons, ranges, and multiple conditions. - Use
match/casefor readable value cases or structured data patterns in Python 3.10+. - Dictionary keys are type-sensitive:
1is not the same key as .
FAQ
What replaces a switch statement in Python?
For fixed mappings, use a dictionary. For conditional logic, use if/elif/else. Python 3.10+ also provides match/case.
Is match/case the same as switch in Python?
It can handle simple switch-like cases, but it also supports structural pattern matching, such as matching lists, mappings, and class attributes.
When should I use a dictionary instead of if/elif?
Use a dictionary when you match exact known keys to values or handlers. Use if/elif when the logic uses ranges, comparisons, or combined conditions.
Does dict.get() raise KeyError?
No. It returns None by default, or the fallback value you provide. mapping[key] raises KeyError for a missing key.
Can a dictionary replace switch cases that run functions?
Mini Project
Description
Build a delivery-zone quote helper for a checkout system. It converts a zone code into a fixed shipping price and clearly handles unsupported zones. This demonstrates the common dictionary-as-switch pattern used for configuration-style mappings.
Goal
Create a function that returns the shipping price for a known delivery zone and raises a helpful error for an unknown zone.
Requirements
Use a dictionary to store at least three zone-to-price mappings.
Create a function that accepts a zone code.
Return the matching price for valid zone codes.
Treat zone codes without regard to leading/trailing whitespace or letter case.
Raise ValueError when the zone code is unsupported.
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Add Rows to a Pandas DataFrame in Python
Learn how to add rows to a Pandas DataFrame, why repeated row appends are slow, and when to use loc, concat, or record lists.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.