Skip to content

#312: Switch Statement in Python

For a long time, there was no switch/case statement in Python. Instead, we had to use a cascade of if/elif/else to filter for the different cases. But with Python 3.10 that changed and now we can use match / case to save us some typing. Let us see how this works.

Structural Pattern Matching

PEP 634 brought us structural pattern matching to Python and works like the well-known switch statement in other languages. The syntax looks like this:

1
2
3
4
5
6
7
8
9
match subject:
    case <pattern_1>:
        <action_1>
    case <pattern_2>:
        <action_2>
    case <pattern_3>:
        <action_3>
    case _:
        <action_wildcard>

The _ is for the default case, when nothing else matches. If we skip that part and run it with a value that has no matching case filter, then nothing happens.

A basic example

As a first example, we can take the code from the official documentation and make this little HTTP status to text translator:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something is wrong with the internet"  

If we run the code, we get this output:

1
2
3
4
>>> http_error(400)
'Bad request'
>>> http_error(500)
'Something is wrong with the internet'

Check for multiple values

We can check for multiple values in the same case statement by using the | operator:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 401 | 403:
            return "Not allowed"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something is wrong with the internet"  

This gives us the same text back for the 3 different values:

1
2
3
4
>>> http_error(401)
'Not allowed'
>>> http_error(403)
'Not allowed'

Logic in the case statement

We can use if statements in our case statement and create a more generic filter to match the right case:

1
2
3
4
5
6
7
8
def classify_number(n):
    match n:
        case x if x < 0:
            return f"negative: {x}"
        case 0:
            return "zero"
        case x if x > 0:
            return f"positive: {x}"

The variable we used in our case statement stays around and we can access it in the code that runs if we have a match:

1
2
3
4
5
6
>>> classify_number(-10)
'negative: -10'
>>> classify_number(0)
'zero'
>>> classify_number(23)
'positive: 23'

Matching dictionaries

We can pass a dictionary down to our match / case statement and filter on different values inside the dictionary:

1
2
3
4
5
6
7
8
def handle_event(event):
    match event:
        case {"type": "user_created", "user_id": user_id}:
            print(f"User created: {user_id}")
        case {"type": "user_deleted", "user_id": user_id}:
            print(f"User deleted: {user_id}")
        case _:
            print("Unknown event")

Depending on what is in the dictionary, we run a different case statement:

1
2
3
4
>>> handle_event({"type": "user_created", "user_id": 11, "email": "info@..."})
User created: 11
>>> handle_event({"type": "user_deleted", "user_id": 6, "date": "2026-01-02 16:19:29"})
User deleted: 6

Destructuring Sequences

If we have sequences like lists or tuples, we can unpack them on the go and check for a certain number of values:

1
2
3
4
5
6
7
8
def parse_coordinates(value):
    match value:
        case [x, y]:
            return f"2D point: {x}, {y}"
        case [x, y, z]:
            return f"3D point: {x}, {y}, {z}"
        case _:
            return "Invalid coordinates"

Depending on our input, we can parse our coordinates into points:

1
2
3
4
5
6
>>> parse_coordinates((1))
'Invalid coordinates'
>>> parse_coordinates((1,2))
'2D point: 1, 2'
>>> parse_coordinates((1,2,3))
'3D point: 1, 2, 3'

Conclusion

Having a switch statement in Python in the form of match / case is a great help. Not only does it save us from a long cascade of if/elif/else, but it also allows us to get a lot of work done without writing many lines of code. Checking for parts of directories or taking sequences apart is a massive help when we have to deal with such cases. Try it!