This article will give you an overview of what the new "match...case" syntax is in Python 3.10 and how it is used. We’ll then dive even deeper into advanced usage.
The "match...case" syntax is similar to switch statements in other Object-oriented languages, and it is meant to make matching a structure to a case easier.
Let’s get started!
The Syntax
The "match...case" syntax is as follows:
def greeting(message):
match message.split():
case ["hello"]:
print("this message says hello")
case ["hello", name]:
print("This message is a personal greeting to {name}")
case _:
print("The message didn’t match with anything")
Let’s go through the syntax to see how it works.
The function that we created takes in one parameter called message
. The match
keyword takes in an object to compare the listed cases to.
In our example, the match keyword takes in a list of strings, which is the result of the message.split()
operation. For further illustration, let’s say we call the function like this:
greeting("hello")
The function first would split this string on all the spaces, and make a list. For the above input, the match
operator would use the list of ["hello"]
. It then compares the list with each case. Our first case is:
case ["hello"]
Our input matches this exactly, so the code continues executing under this case.
Output:
this message says hello
What if we called the function like this: greeting("hello George")
?
Using that input, the match operator would be using a list of ["hello", "George"]
to compare all the cases against. The first case, case "hello"
, would not match because the comparison list has two elements in it, not one.
Structural matching
The match operator matches the structure of the expression that it is given. So our first case does not match due to the length of the case expression, even though the comparison expression matches with the first element in the list.
The second case is ["hello", name]
. This is the case that our input matches with. If you don’t give a literal value for Python to match with, it will bind whatever value there is in the comparison expression to the variable name in the case expression. So in our example, name
would be set to George
. And this case matches (it has "hello"
as the first element, and has one more element, which gets bound to name
), so the output is:
This message is a personal greeting to George
Now let’s try calling the function like this: greeting("hello George Johnson")
.
The comparison expression becomes ["hello", "George", "Johnson"]
. Now let’s go through each case. The first case fails, because the comparison expression has 3 elements in it, and not 1. The second case fails in the same way; the second case expects to see a list of length 2 where the first element is "hello"
. The first element is in fact "hello"
, but the comparison expression has 3 elements, so this case does not match.
The only option left is the underscore case, which is the default, match-everything case. Think of it like the default
case in switch statements. If a comparison expression doesn’t match with anything else, it will always match with the _
case.
Underscore as the last case
Any cases below this case will never run because all cases will match with the underscore case. This is similar to the else
keyword in an if...else.
The _
case matches everything because Python recognizes _
as a valid variable name. So just like when we matched the case ["hello", name]
, the comparison expression will get binded to the _
name. In our specific case, the _
variable would hold the value ["hello", "George", "Johnson"]
.
So in our latest function call, greeting("hello George Johnson")
, the output would be:
The message didn’t match with anything
Advanced Usage
The "match...case" syntax is a very powerful tool and can be used to compare many different expressions and values. If you are comparing a list as we did in the above example, there are a few more features of match
that you can use.
In the case
expression, you can use an operator to put all remaining elements into a variable. For example:
comparison_list = ["one", "two", "three"]
match comparison_list:
case [first]:
print("this is the first element: {first}")
case [first, *rest]:
print("This is the first: {first}, and this is the rest: {rest}")
case _:
print("Nothing was matched")
In this snippet, the second case would match and execute, with the output being:
This is the first: one, and this is the rest: ["two", "three"]
You can also compose the case branches out of two or more structures, like so:
match comparisonList:
case [first] | [first, "two", "seven"]:
print("this is the first element: {first}")
case [title, "hello"] | ["hello", title]:
print("Welcome esteemed guest {title}")
case [first, *rest]:
print("This is the first: {first}, and this is the rest: {rest}")
case _:
print("Nothing was matched")
The first and second cases are made up of a few different expressions that the comparison expression could fit into for the case branch to run. This gives you some flexibility to compose your branches out of.
We will also cover the "match...case" syntax for dictionaries. The match operator will check to see if the comparison expression contains the properties that are in the case expressions. For example:
comparisonDictionary = {
"John": "boy",
"Jack": "boy",
"Jill": "girl",
"Taylor": "girl"
}
match comparisonDictionary:
case {"John": "boy", "Taylor": "boy"}:
print("John and Taylor are both boys")
case {"John": "boy", "Taylor": "girl"}:
print("Taylor is a girl and John is a boy")
case _:
print("Nothing matches")
Would output:
Taylor is a girl and John is a boy
The match
operator will check to see if the case property exists on the input dictionary, then it will check to see if the values match.
Important
In dictionary matching, the case
will still match even if the input dictionary has more properties than the ones that the case
specifies.
If you want to dive even deeper, see here for the official documentation.
Case Closed!
In all, the new "match...case" operator is a powerful tool for Python developers to leverage when creating branching cases. With it, you can robustly check the structure of any incoming variable and ensure that you won’t try to access something that is not present on the variable.
If you want to learn more about Python, consider enrolling in our Complete Python Course which takes you from beginner all the way to advanced (including OOP, web development, async development, and much more!). We have a 30-day money-back guarantee, so you really have nothing to lose by giving it a try. We'd love to have you!