Python ‘switch case’ Statement: A Complete Guide (match case)

Python switch-case statements are here as of Python 3.10! These statements are actually called match-case statements.

With a match-case statement, you can get rid of rather verbose if-elif-else chains like this:

http_status = 400

if http_status == 400:
    print("Bad Request")
elif http_status == 403:
    print("Forbidden")
elif http_status == 404:
    print("Not Found")
else:
    print("Other")

Instead, you can use a compact match-case expression to do the exact same:

http_status = 400

match http_status:
    case 400:
        print("Bad Request")
    case 403:
        print("Forbidden")
    case 404:
        print("Not Found")
    case _:
        print("Other")

In some situations, the latter approach is better. It can make the code more readable and less repetitive.

This guide teaches you everything about Python match-case statements. You are going to take a look at the common problem with if-else statements. Besides, you will learn how match-case statements can fix this problem. Last but not least, you learn 5 different situations in which you can use the match-case statements.

Without further ado, let’s jump into it!

The Problem with If-Else in General

Speaking of any programming language, if-else statements are not always the most intuitive way to make comparisons. This is especially true when the if-else statements are repetitive and lengthy.

To see an example, let’s write a pseudocode script that checks the day of the week using if-else statements:

day = "Monday"

if day == "Sunday" {
    print("Take it easy")
}
else if day == "Monday" {
    print("Go to work")
}
else if day == "Tuesday" {
    print("Work + Hobbies")
}
else if day == "Wednesday" {
    print("Meetings")
}
else if day == "Thursday" {
    print("Presentations")
}
else if day == "Friday" {
    print("Interviews and party")
}
else if day == "Saturday" {
    print("Time to do sports")
}

In this piece of code, there is a lot of repetition, as you can tell.

Each else-if check repeats day == “something”. But it is clear you are referring to day in each comparison. So it would be great if you did not need to repeat the day == “something” in each comparison you make. This would make the code look cleaner and shorter.

This gives rise to a neat solution called the switch-case statement. This solution is commonly present in popular programming languages.

The Solution—Switch Case Statements

The switch-case statement combines if-else statements into a smoother pattern-matching structure.

Using switch-case, you specify the value you are interested in and specify patterns (cases) for each possible outcome. The code then tries to match the value with the patterns.

Using a switch-case statement helps you avoid repetition and makes the code clean.

Here is a pseudocode example of replacing the above if-else mess with switch-case:

day = "Monday"

switch day {
  case "Sunday"   : print("Take it easy")
  case "Monday"   : print("Go to work")
  case "Tuesday"  : print("Work + Hobbies")
  case "Wednesday": print("Meetings")
  case "Thursday" : print("Presentations")
  case "Friday"   : print("Interviews and party")
  case "Saturday" : print("Time to do sports")
}

This looks way cleaner and is much shorter than the if-else mess you saw in the previous section.

The switch-case is seen in popular programming languages, such as C++.

Python 3.10 also supports switch-case statements. But they go with a different name—match-case statements.

Let’s take a deeper dive into the match-case statements in Python.

Match Case Statement—Python’s Version of Switch Case

Python versions of 3.10+ start supporting the switch-case statement. Notice how in Python, it is called match-case, not switch-case.

The match-case statement is also known as structural pattern matching.

The problem match-case solves is described in the previous chapter. In short, it replaces repetitive if-else statements with a compact pattern-matching structure.

Match Case in Python

In Python, the general structure for match-case pattern matching follows this syntax:

match element:
  case pattern1:
    # statements
  case pattern2:
    # statements
  case pattern3:
    # statements

In this code construct:

  • The match element means “match the element with the following patterns”
  • Then each case pattern statement compares the element with the specified pattern. This can for example be a string or number.
  • If a pattern matches with the element, the corresponding block of code gets executed. After that, the match-case statement is exited.

So the idea is exactly the same as with an if-elif-else statement but with less repetition.

Example

Let’s implement the weekday pseudocode example you saw earlier using Python. The regular if-else approach would look like this:

day = "Monday"

if day == "Sunday":
    print("Take it easy")
elif day == "Monday":
    print("Go to work")
elif day == "Tuesday":
    print("Work + Hobbies")
elif day == "Wednesday":
    print("Meetings")
elif day == "Thursday":
    print("Presentations")
elif day == "Friday":
    print("Interviews and party")
elif day == "Saturday":
    print("Time to do sports")

This piece of code works, but it looks like a complete mess. With Python 3.10 match-case statement, you can prettify the code quite a bit.

Here is a match-case version of the above code:

day = "Monday"

match day:
    case "Sunday"    : print("Take it easy")
    case "Monday"    : print("Go to work")
    case "Tuesday"   : print("Work + Hobbies")
    case "Wednesday" : print("Meetings")
    case "Thursday"  : print("Presentations")
    case "Friday"    : print("Interviews and party")
    case "Saturday"  : print("Time to do sports")

Doesn’t it look much better? Once you adapt to reading the match case structure, this code becomes much more readable than the if-else mess earlier.

By the way, you can also break the case expressions to expand to multiple lines if that’s more convenient.

Here is the above code where each expression is on its own line:

day = "Monday"

match day:
    case "Sunday":
        print("Take it easy")
    case "Monday":
        print("Go to work")
    case "Tuesday":
        print("Work + Hobbies")
    case "Wednesday":
        print("Meetings")
    case "Thursday":
        print("Presentations")
    case "Friday":
        print("Interviews and party")
    case "Saturday":
        print("Time to do sports")

Now you have a basic understanding of how match-case statements can simplify your if-else statements.

To recap, instead of using verbose and repetitive if-else statements to perform condition checks, you might want to use match-case pattern matching.

Speaking of matching patterns, let’s move on to learn what kinds of patterns you can match with using the match-case statements.

5 Common Match Case Pattern Types

There are different types of patterns you can match with using the match-case statements. The most notable patterns include:

  1. Literal patterns
  2. Capture patterns
  3. Wildcard patterns
  4. Constant value patterns
  5. Sequence patterns

Let’s go through each pattern in more detail.

Pattern 1: Literal Patterns

The most basic use case for match cases is matching with literal patterns. The literal you can match with can be a:

  • Number
  • String
  • None
  • True
  • False

A good example of literal pattern matching is the weekday example. In this example, we match a string literal with a variable day:

day = "Monday"

match day:
    case "Sunday"    : print("Take it easy")
    case "Monday"    : print("Go to work")
    case "Tuesday"   : print("Work + Hobbies")
    case "Wednesday" : print("Meetings")
    case "Thursday"  : print("Presentations")
    case "Friday"    : print("Interviews and party")
    case "Saturday"  : print("Time to do sports")

This code checks what value the variable day has. Based on this, it performs an action, which in this case is a simple console print.

Pattern 2: Capture Patterns

You can use the match-case statement to store (capture) a matched value to a variable.

This is best demonstrated with an example.

For example, let’s create a function greet() that greets a person if a name is specified.

def greet(name=None):
    match name:
        # Check if name == None
        case None:
            print("Hello there")
        # Store name into some_name if it is not None
        case some_name:
            print(f"Hello {some_name}")


greet()       # Prints "Hello there"
greet("Jack") # Prints "Hello Jack"

This match-case statement does two things (as highlighted in the comments):

  • Checks if the name is None. If it is, the default greeting message shows up in the console.
  • Checks if the name matches with something else than None. If it does, that name is stored into some_name. The program then greets this name in the console.

Pattern 3: Wildcard Pattern

When using match-case, you can use a wildcard pattern to match without binding. To understand what this means, the wildcard pattern matches with anything not included in the case statements. In a sense, the wildcard pattern is the “else” block of a match-case statement.

To create a wildcard pattern, use the underscore _.

1. Use Case Example

For example, let’s match for a result of a coin flip:

coinflip = 4

match coinflip:
    case 1:
        print("Heads")
        exit()
    case 0:
        print("Tails")
    case _:
        print("Must be 0 or 1.")

Output:

Must be 0 or 1.

Here the wildcard case matches with anything else than 0 or 1. So in the above example, the coinflip result is accidentally 4. The wildcard notices this and runs the associated action.

This is one way you can use the wildcard pattern in match-case statements.

2. Use Case Example

Another use case for the wildcard pattern is if you don’t care about the value of the match. This is useful when you want to make sure there is a value (or a group of values), regardless of what that value is.

For example, let’s check the dimension of a tuple without caring about its values:

location = (0, 0)

match location:
    case(_,):
        print("1D location found")
    case(_, _):
        print("2D location found")
    case(_, _, _):
        print(("3D location found"))

Output:

2D location found

As you can see, this match-case only cares about the number of elements found. In this case, you used the wildcard to verify there are two elements in the tuple without caring about the individual values.

You could do the same using an if-else statement and the len() function. But in case the if-else statements become too long, you should use a match-case statement for improved code quality.

Pattern 4: Constant Value Patterns and Enumerations

You can use enumeration items as patterns in a match-case statement. In case you are unfamiliar with enumerations, see this article.

To demonstrate how an enumeration and match-case statement can be used:

  • Let’s create a Direction enumeration that represents the four main directions in the compass.
  • Let’s also create a function handle_directions() that takes a direction as input. This function matches the direction with one of the directions from the enumeration and reacts accordingly.

Here is the code:

from enum import Enum

class Direction(Enum):
    NORTH = 1
    EAST = 2
    SOUTH = 3
    WEST = 4

def handle_directions(direction):
    match direction:
        case Direction.NORTH: print("Heading North")
        case Direction.EAST: print("Heading East")
        case Direction.SOUTH: print("Heading South")
        case Direction.WEST: print("Heading West")

Now you can call handle_directions() this way for example:

handle_directions(Direction.NORTH)

Obviously, you could replace the above code with something much shorter or simpler. But this example demonstrates how you can use enumerations and match-case statements.

The reason why you may want to do this is that you don’t want to use so-called mystic strings in your code. For more details on what this means, see this article.

Pattern 5: Sequence Patterns

You can unpack the values of a sequence in pattern matching.

If you don’t know what unpacking is, it means pulling the values of a sequence into separate variables.

Here is an example of unpacking four list values from a list of directions:

directions = ["North", "East", "South", "West"]

# Grab the values from a list and store them into variables
n, e, s, w = directions

print(n) # prints North
print(e) # prints East
print(s) # prints South
print(w) # prints West

Now, you can also use unpacking in conjunction with a match-case statement.

For example, let’s check if a location is a 1D, 2D, or 3D point. Besides, let’s store the coordinate values into separate variables based on the number of dimensions.

location = (1, 3)

match location:
    case x, :
        print(f"1D location found: ({x})")
    case x, y:
        print(f"2D location found: ({x}, {y})")
    case x, y, z:
        print((f"3D location found: ({x}, {y}, {z})"))

Output:

2D location found: (1, 3)

The code matches location with a tuple of one, two, or three elements. The coordinate values are then unpacked to separate variables.

If you have more values, but you care about the first three, you can use the * operator. This accounts for “the rest of the elements”.

For instance, let’s say you have a tuple location that represents coordinates. In addition, it can store additional elements. To catch the extra items, let’s use the * operator:

location = (1, 3, 2, "a", "b", "c")

match location:
    case x, :
        print(f"1D location found: ({x})")
    case x, y:
        print(f"2D location found: ({x}, {y})")
    case x, y, z, *names:
        print((f"3D location found: ({x}, {y}, {z})"))
        print(f"Also, there was some extra data: {names}")

Output:

3D location found: (1, 3, 2)
Also, there was some extra data: ['a', 'b', 'c']

Now *names captures all “the rest” of the elements in the location tuple—no matter how many extra elements there are.

Now you know the basic pattern types you can match against. Last but not least, let’s take a look at how to combine patterns in a match-case statement.

Combining Patterns in Match Case

It is possible to compare patterns in a match-case statement.

To do this, use the logical or operator |. This checks if at least one pattern matches the value.

For example, let’s match days based on if they are weekends or not:

day = "Monday"

match day:
    case "Saturday" | "Sunday":
        print("Weekend")
    case "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday":
        print("Work")

Output:

Work

Conclusion

In a typical programming language, you can replace lengthy if-else statements with neater switch-case statements.

In Python 3.10, a similar feature was released. In Python, it’s not called switch-case, but match-case.

Here is an example of a match-case statement:

http_status = 400

match http_status:
    case 400:
        print("Bad Request")
    case 403:
        print("Forbidden")
    case 404:
        print("Not Found")
    case _:
        print("Other")

The match-case statement matches a value with a group of patterns. If there is a match, the corresponding piece of code is executed.

Match-case works similarly to if-else statements. The main difference is you don’t need to repeat the name of the compared item.

Thanks for reading. I hope you find it useful.

Happy coding!