Choose a switch alternative in Python

Use match-case for structured patterns, if-elif for conditions, and dictionary dispatch for fixed keys without confusing captures with constants.

Best practices
Python programming and application logging

Python 3.10 introduced match and case for structural pattern matching. Use it when branches depend on the shape or contents of data. if/elif remains useful for conditions and ranges; dictionaries work well for fixed key-to-value or key-to-function mappings.

Match literal values

def describe_status(status):
    match status:
        case 200:
            return "Success"
        case 404:
            return "Not found"
        case 500 | 502 | 503:
            return "Server error"
        case _:
            return "Unknown status"

The first matching case whose guard passes is selected. There is no C-style fall-through and no need for break. The | pattern matches alternatives; _ is a wildcard.

Pattern matching can also extract fields:

def payload_data(payload):
    match payload:
        case {"code": 200, "data": data}:
            return data
        case _:
            return None

This mapping pattern permits additional keys. A bare name in a pattern normally captures a value; it does not compare against a variable with that name. Use a literal, a qualified constant such as Status.OK, or a guard when comparison is intended.

Use conditions for ranges

def classify_score(score):
    if score >= 90:
        return "High"
    elif score >= 60:
        return "Passing"
    return "Low"

Order matters when conditions overlap. This approach works on Python versions before 3.10 too. A match guard can express conditions, but is not necessary for a simple range check.

Map fixed values or functions

messages = {200: "Success", 404: "Not found", 500: "Server error"}
print(messages.get(404, "Unknown status"))

def create_handler():
    return "Created"

def delete_handler():
    return "Deleted"

handlers = {"create": create_handler, "delete": delete_handler}
action = "create"
handler = handlers.get(action)
if handler is None:
    raise ValueError(f"Unsupported action: {action}")
print(handler())

Store function objects, not the result of calling them while building the dictionary. Decide whether an unknown action should raise, return a default, or follow another explicit path.

FAQ

Which option is fastest? It depends on the workload and implementation. Dictionary lookup is generally expected constant time, but pattern matching can perform structural work and conditions may be cheap. Choose for semantics first and measure only when necessary.

Can a dictionary represent numeric intervals? An ordinary direct lookup matches exact hashable keys. Use conditions, explicit boundary lookup with bisect, or a specialized interval structure when ranges are the actual problem.

References

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting