Skip to content

Python Switch (Match-Case) Statements: Complete Guide

Python Match Case Switch Statement Tutorial Cover Image

In this tutorial, you’ll learn how to use Python to create a switch-case statement. Prior to Python version 3.10, Python did not have an official switch-case statement. In order to accomplish this, you had a number of different options, such as if-else statements and dictionaries.

By the end of this tutorial, you’ll have learned:

  • How to use Python Switch-Case Statements in Python 3.10+
  • What some use cases for Python Switch-Case Statements are
  • How to emulate switch-case statements in older versions of Python, using dictionaries, if-else statements, and classes

What are Switch-Case Statements?

A switch or case statement is a statement that evaluates an expression against a case and then executes some code. It’s a method by which programming languages can control the flow of the program, based on a condition (or conditions) being met.

For many years, Pythonistas have been seeking switch-case statements. They are common in most other programming languages and many felt it was an odd omission to not include them in the language. This required Python programmers to use different methods, such as if-else statements, to emulate the switch statement.

In 2020, via PEP 634, Python introduced the concept of Structural Pattern Matching in Python. This represents the switch-case statements finally coming to Python in an official manner! What’s more, is that Python actually extends beyond a simple case statement and provides flexible matching control.

How Do Switch-Case Statements Work in Python?

Beginning in Python version 3.10, you now have access to switch-case statements in Python! Creating a Python match statement is simple: match some variable to a case (or multiple cases). Let’s start by looking at a straightforward example:

# Building a simple match-case statement in Python
response_code = 400

match response_code:
    case 200:
        print("Everything's peachy!")
    case 300:
        print("You're going somewhere else!")
    case 400:
        print("Uh oh. Are you lost?")
    case 500:
        print("Yikes. Something went wrong!")

# Returns:
# Uh oh. Are you lost?

We can see that this was a fairly straightforward example! However, you may also know that HTTP response codes are a bit more elaborate. For example, you could have 301, 404, and so on.

In the next section, you’ll learn how to use conditions in your Python match statements.

Matching Combined Cases in Python Match-Case Statements

We know that HTTP status codes won’t just be exactly 200, 300, 400, and 500. We could write length statements for each, but some of them can be combined. In Python match-case statements, we can do this using the or (pipe) operator, |.

# Combining cases in Python match-case statements
response_code = 404

match response_code:
    case 400:
        print("Server can't understand.")
    case 401 | 403:
        print("Server refused to send back.")
    case 404:
        print("Server can't find.")

# Returns:
# Server can't find.

By combining some of our conditions, our code is both easier to write and to read.

Matching Patterns in Python Match-Case Statements

What’s great about Python match-case statements is that they allow for matching different conditions. Because HTTP response codes are broken into 2xx, 3xx, 4xx, and 5xx style values, we can look at the first value in that response and return a switch-case:

# Matching patterns in Python match-case statements
response_code = 301

match int(str(response_code)[0]):
    case 2:
        print("Everything's peachy!")
    case 3:
        print("You're going somewhere else!")
    case 4:
        print("Uh oh. Are you lost?")
    case 5:
        print("Yikes. Something went wrong!")

# Returns:
# You're going somewhere else!

Providing a Default Value in Python Match-Case Statements

Python also makes it very easy to add default cases to your match-case statements. Because Python evaluates against a pattern, you can simply provide a disposable variable, conventionally _, to replace a catch-all case.

Let’s see how this can work:

# Providing default cases
response_code = 600

match int(str(response_code)[0]):
    case 2:
        print("Everything's peachy!")
    case 3:
        print("You're going somewhere else!")
    case 4:
        print("Uh oh. Are you lost?")
    case 5:
        print("Yikes. Something went wrong!")
    case _:
        print("Yikers. I don't know that one.")

# Returns:
# Yikers. I don't know that one.

Matching Type and Structure in Python Match-Case Statements

Another incredible feature of Python is the ability to match both a type and a structure. This means that Python can interpret whether an item is, say, an iterable object from which it can extract values. Similarly, it can look at the size and makeup of that structure to glean meaning.

Let’s take a look at a simple example:

# Matching structure in Python switch-case
match values:
    case [a]:
        print(f'Only one item: {a}')
    case [a, b]:
        print(f'Two items: {a}, {b}')
    case [a, b, c]:
        print(f'Three items: {a}, {b}, and {c}')
    case [a, b, c, *rest]:
        print(f'More than three items: {a}, {b}, {c}, as well as: {rest}')

Here, our match-case statement evaluates for the structure. In particular, if the list only has a single item, the first case is run:

# Matching a structure
values = ['John']

# Returns:
# Only one name: John

Let’s take a look at the case where more than three items are included. We use the * to unpack any items following the first. This means that it doesn’t matter how many items are in that list:

# Matching a complex structure
values = ['John', 'Matt', 'Kate', 'Nik', 'Evan']

# Returns:
# More than three names: John, Matt, Kate, as well as: Nik, Evan

Checking Types in Python Match-Case Statements

Python match-case statements can also be used to check the types of something being passed in. Let’s move this to a more advanced example and create a function that let’s us pass in different values.

# Checking types with 'as' in Python match-case statements
def type_of(var):
    match var:
        case int() | float() as var:
            return "Number"
        case dict() as var:
            return "Dictionary"
        case list() | tuple() | set() as var:
            return "List, tuple, or set"
        case str() as var:
            return "String"
        case _:
            return "Something else"

print(type_of(3))
print(type_of({1,2}))

# Returns:
# Number
# List, tuple, or set

Guarding Python Match-Case Statements

Another helpful thing Python match-case statements can do is guard certain cases from being executed.

Let’s say you received a dictionary that contained a student’s name, the number of courses they’ve taken, and their overall grade. You wanted to award students different awards based both on the number of courses and their overall grade.

You can write guarded case statements in this case using the if keyword, which works similar to the in-line if in Python.

# Guarding Python match-case statements with inline if
def award(student):
    match student:
        case {'name': name, 'courses': courses, 'grade': grade} if courses > 15 and grade >= 90:
            return f"{name}: Exceptional"
        case {'name': name, 'courses': courses, 'grade': grade} if grade >= 90:
            return f"{name}: Future star"
        case _:
            return f"{name}: No current award"



print(award({'name': 'Kate', 'grade':90, 'courses':16}))
print(award({'name': 'Jane', 'grade':80, 'courses':16}))

# Returns:
# Kate: Exceptional
# Jane: No current award

In this case, we first provide values for our dictionary in our match. Using these variables, we can then guard against them as well as use them in our resulting return statement.

How to Create Switch-Case Statements in Python with if-else

In this and the following three sections, you’ll learn how to emulate Python match-case statements using different methods prior to Python version 3.10. In this section, you’ll learn how to use if-else statements to emulate switch-case statements in Python.

All of the above examples will work, they’ll just not look as elegant or as clean. Let’s start with a more basic example first:

# Building a simple SWITCH statement in Python with if-else
response_code = 400

if response_code == 200:
    print("Everything's peachy!")
elif response_code == 300:
    print("You're going somewhere else!")
elif response_code == 400:
    print("Uh oh. Are you lost?")
elif response_code == 500:
    print("Yikes. Something went wrong!")

# Returns:
# Uh oh. Are you lost?

We can see that this looks very similar to the switch-case statements we wrote above. However, we are required to consistently repeat the value of our variable to evaluate against. In this case, that still looks ok, but if our conditions get longer and longer that can prove different.

Similarly, we can provide a catch-all response if no conditions are met, using the else keyword:

# Providing a default value in if-else
# Building a simple match-case statement in Python
response_code = 1200

if response_code == 200:
    print("Everything's peachy!")
elif response_code == 300:
    print("You're going somewhere else!")
elif response_code == 400:
    print("Uh oh. Are you lost?")
elif response_code == 500:
    print("Yikes. Something went wrong!")
else:
    print("I don't understand.")

# Returns:
# I don't understand.

How to Create Switch-Case Statements in Python with Dictionaries

While the if-else statement provides a lot of flexibility, it’s often less elegant to write and to read. Dictionaries can be used for simple switch-case statements, that can even execute functions.

Let’s take a look at an example, where we pass in a month number and it returns a season:

seasons = {
    1: 'winter',
    2: 'winter',
    3: 'winter',
    4: 'spring',
    5: 'spring',
    6: 'spring',
    7: 'summer',
    8: 'summer',
    9: 'summer',
    10: 'fall',
    11: 'fall',
    12: 'fall',
}

print(seasons[1])

# Returns: winter

If instead we didn’t want to simply return a value, we could define some functions and have the value of our dictionaries be the callables of those functions:

def winter():
    return 'Brr'

def spring():
    return 'Flowers everywhere!'

def summer():
    return 'Beach time!'

def fall():
    return 'Pumpkins and apple cider!'

seasons = {
    1: winter(), 2: winter(), 3: winter(), 4: spring(), 5: spring(), 6: spring(), 
    7: summer(), 8: summer(), 9: summer(), 10: fall(), 11: fall(), 12: fall()}

print(seasons[1])

# Returns: Pumpkins and apple cider!

We can see how this can be quite useful for extending program behavior given certain conditions. You could, for example, get the dictionary value from an HTTP request and run different pieces of code given the status code of the request.

Conclusion

Python version 3.10 opens up a new world of possibility with incredibly versatile match-case statements. This article explored what switch-case statements are and how to use them in a variety of ways. You learned how to build simple statements, conditional statements, and statements that guard or extract additional information.

Finally, you also learned how to use Python if-else statements and dictionaries to emulate switch-case statements for older versions of Python.

Additional Resources

To learn more about related topics, check out the tutorials below:

Tags:

Leave a Reply

Your email address will not be published.