Back to articles list Articles
7 minutes read

How to Use a match case Statement in Python 3.10

The Python programming language is under constant development, with new features and functionality added with every update. Python 3.10 was released in mid-2021 and comes with structural pattern matching, also known as a match case statement. This is Python 3.10’s most important new feature; the new functionality allows you to more easily control the flow of your programs by executing certain parts of code if conditions (or cases) are met.

In this article, we’ll tell you everything you need to know about the match case statement in Python, which will allow you to have fine-grained control over how your programs execute.

A Word About Python Versions

Before we get started, let’s first address Python versions and basic Python knowledge.

If you’re running an older version of Python, we’d like to encourage you to upgrade to Python 3.10 to get the most out of this article. This will allow you to use the code snippets here and be able to modify them to suit your own projects.

Check out the official Python downloads page for access to the most recent versions. If you want more detailed information on match case statements, there are three new Python Enhancement Proposals (PEPs).  A good place to start is PEP 636, which is a tutorial for pattern matching. If you want to get deep into the weeds, PEP 634 covers the specification and PEP 635 describes the motivation and rationale for this new feature.

For those of you who are new to Python, we have two articles explaining some important terms we’ll be using in this article. Check out part 1 here, and part 2 here.  We also have interactive courses to help accelerate your learning. Python Basics is a good starting point, and Built-in Algorithms in Python will teach you the tools to write optimized applications in no time.

Okay, now let’s dig into the Python match case statement.

The match case Statement in Python

A basic implementation of match case statements looks a lot like an if statement in Python. If you need a refresher, we have an article on checking multiple conditions in Python with an if statement.

For those of you who have some background in other languages like Java or C, match case may look like a switch statement. Switch statements are functionally similar to if-else statements, but they require less code when defining the cases.

The match case statement in Python is more powerful and allows for more complicated pattern matching. Let’s start by looking at a basic example to demonstrate the syntax:

>>> command = 'Hello, World!'
>>> match command:
...     case 'Hello, World!':
...         print('Hello to you too!')
...     case 'Goodbye, World!':
...         print('See you later')
...     case other:
...         print('No match found')

Hello to you too!

Here we define a variable command and use the match keyword to match it to the cases defined after each case keyword.  As a side note, match and case are better described as “soft” keywords, meaning they only work as keywords in a match case statement.  You can keep using “match” or “case” as a variable name in other parts of your program.  The case other is equivalent to else in an if-elif-else statement and can be more simply written as case _.

We’re using the print() function here to simply print text to the screen. But any other commands or function calls can go here to be executed if the case is matched.  We’ll see some more detailed examples below. If you want to learn more about the print() function, take a look at this article.

Why Use a match case Statement?

The example above can just as easily be implemented with an if-elif-else statement. In this section, we’ll see two more examples of how using match case can simplify your flow control statements, making them more readable and less prone to errors. 

Say we want to write a script to handle a large number of files. We can write the following function:

>>> def file_handler_v1(command):
...     match command.split():
...         case ['show']:
...             print('List all files and directories: ')
...             # code to list files
...         case ['remove', *files]:
...             print('Removing files: {}'.format(files))
...             # code to remove files
...         case _:
...             print('Command not recognized')

The input is again a string which gets split at white space using command.split(). This returns a list of strings. (By the way, if you are wondering what the difference between lists and arrays is, we explain it in this article.) The first case is matched when the value  of command is 'show', for which the split() method returns the list ['show'].  Then code to list all files in a particular directory gets executed. Here we just have the code to be executed indicated by comments; in reality, you could use the os module to implement the required functionality.

The second case is more interesting. Here’s an example:

>>> file_handler_v1('remove file1.txt file2.jpg file3.pdf')
Removing files: ['file1.txt', 'file2.jpg', 'file3.pdf']

The first part of the argument 'remove' is matched after splitting.  Using the starred expression in the case definition captures any number of optional arguments which follow (similar to *args); the files variable gets defined as a list containing all the files to be removed. If you try implementing this with an if-elif-else statement, you’ll use more code to achieve the same result. It will also not be as readable as using a match case statement.

The next level of complexity involves using an or operator (|) and putting an if statement inside the case definition. Take a look at the following function, paying particular attention to the second and third cases:

>>> def file_handler_v2(command):
...     match command.split():
...         case ['show']:
...             print('List all files and directories: ')
...             # code to list files
...         case ['remove' | 'delete', *files] if '--ask' in files:
...             del_files = [f for f in files if len(f.split('.'))>1]
...             print('Please confirm: Removing files: {}'.format(del_files))
...             # code to accept user input, then remove files
...         case ['remove' | 'delete', *files]:
...             print('Removing files: {}'.format(files))
...             # code to remove files
...         case _:
...             print('Command not recognized')

The second and third cases now match for either “remove” or “delete” in the input command. Additionally, the second case has an if statement that matches only when the optional flag --ask is in the input. Below this, you could implement code to accept user input, then delete the files if the command is confirmed. Notice we had to select all the files to delete by using a list comprehension, which is a compact way of writing a for loop. Take a look at this article for more information on for loops in Python.

The third case in the above example is matched when the optional flag is not in the input command. Let’s see two examples of this function in action:

>>> file_handler_v2('remove --ask file1.txt file2.jpg file3.pdf')
Please confirm: Removing files: ['file1.txt', 'file2.jpg', 'file3.pdf']

>>> file_handler_v2('delete file1.txt file2.jpg file3.pdf')
Removing files: ['file1.txt', 'file2.jpg', 'file3.pdf']

Final Thoughts on match case Statements in Python

In this article, we’ve introduced structural pattern matching in Python with the match case statement. We showed how it can provide an advantage over an if-elif-else statement in terms of the amount of code needed and the readability. There’s even more this new feature can do that we didn’t touch on here – you can provide an object as an input (instead of the strings we used) and do pattern matching on the attributes of the object. Pretty cool stuff.

A word of caution: for more complex statements like the final example above, the order in which you have the cases changes the behavior of the program. You might be familiar with this from writing if-elif-else statements. To demonstrate this problem, take the final example from above and swap the positions of the second and third cases. You’ll find the --ask flag is never matched. So, make sure you put a bit of thought into how you structure the case statements. You could even incorporate some of the other flow control statements into your code. Check out this article which shows how to use break, continue, and pass to control loops in Python.

Strictly speaking, match case doesn’t add new functionality to Python. However, it does vastly simplify complex control statements. Feel free to take what you’ve learnt here and apply to your own projects. Try to re-write some of your if-elif-else statements with a match case statement to convince yourself of its usefulness. Happy coding!