When we use a long chain of if ... elif ... elif ... else ... conditions, the code can become quite lengthy and less readable.
If you need to check a variable against several specific values, you can use the match statement (available in Python 3.10+).
For example, a student’s grade can only be ‘A’, ‘B’, or ‘C’. Using if statements, you might write:
score = 'B'
if score == 'A':
print('score is A.')
elif score == 'B':
print('score is B.')
elif score == 'C':
print('score is C.')
else:
print('invalid score.')
Rewriting this with a match statement would look like this:
score = 'B'
match score:
case 'A':
print('score is A.')
case 'B':
print('score is B.')
case 'C':
print('score is C.')
case _: # The underscore (_) matches any other value
print('score is ???.')
When using a match statement, you sequentially check for matches using case xxx. You can add a final case _ (and it can only be at the end) to represent a catch-all for “any other value”. This makes the code generally more readable than an equivalent if ... elif ... else ... chain.
Beyond matching simple, single values, the match statement can also handle multiple values, ranges, and can bind the matched value(s) to variables:
age = 15
match age:
case x if x < 10:
print(f'< 10 years old: {x}')
case 10:
print('10 years old.')
case 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18:
print('11~18 years old.')
case 19:
print('19 years old.')
case _:
print('not sure.')
In the example above:
case x if x < 10: matches when age < 10 is true and assigns the value of age to the variable x.case 10: matches only the single value 10.case 11 | 12 | ... | 18: matches any one of the values separated by the | (or) operator.This demonstrates the considerable flexibility of case patterns in a match statement.
The match statement can also match against lists, offering powerful capabilities.
Suppose a user enters a command stored in a list like args = ['gcc', 'hello.c']. The following code demonstrates how to parse this list using match:
args = ['gcc', 'hello.c', 'world.c']
# args = ['clean']
# args = ['gcc']
match args:
# If only 'gcc' is present, report an error:
case ['gcc']:
print('gcc: missing source file(s).')
# If 'gcc' is present with at least one file:
case ['gcc', file1, *files]:
print('gcc compile: ' + file1 + ', ' + ', '.join(files))
# If only 'clean' is present:
case ['clean']:
print('clean')
case _:
print('invalid command.')
case ['gcc']: matches a list containing only the single string 'gcc' (no filenames specified), and prints an error.case ['gcc', file1, *files]: matches a list where the first element is 'gcc', the second element is bound to the variable file1, and any remaining elements are captured into the list files (the role of the * operator will be explained in the context of function parameters). This effectively matches 'gcc' followed by at least one filename.case ['clean']: matches a list containing only the single string 'clean'.case _: matches all other cases.As we can see, the pattern matching rules of the match statement are very flexible, allowing you to write highly concise and expressive code.