Python 3.10 is fresh on the shelves. Let's have a match case to taste it

Posted by cyberRobot on Thu, 21 Oct 2021 01:35:43 +0200

Original link: http://www.juzicode.com/python-note-3-10-match-case

The official version of Python 3.10.0 was finally released at the beginning of this month. One of the important features is that it supports match case statements. This switch case statement similar to C language is finally implemented in Python.

General matching pattern

A typical switch case statement in C language is as follows. The switch contains the variable x to be judged. After the case statement is the value of the matching variable. If this matching condition is met, execute the statements after "case n:" until you encounter a break and exit the switch statement.

//VX: Orange code / juzicode.com
#include <stdio.h>
int main(void)
{
    int x;
    printf("Enter value: "); 
    scanf("%d",&x);
    switch(x){
        case 1: printf("Monday\n"); break;
        case 2: printf("Tuesday\n"); break;
        case 3: printf("Wednesday\n"); break;
        case 4: printf("Thursday\n"); break;
        case 5: printf("Friday\n"); break;
        case 6: printf("Saturday\n"); break;
        case 7: printf("Sunday\n"); break;
        default:printf("Input error\n"); break;
    }
    return 0;
}

In Python 3.10, similar functions can be implemented with match case statements:

#VX: Orange code / juzicode.com
x = int(input("Enter value: "))
match x:
    case 1:print('Monday')
    case 2:print('Tuesday')
    case 3:print('Wednesday')
    case 4:print('Thursday')
    case 5:print('Friday')
    case 6:print('Saturday') #A few statements can be written on the same line
    case 7:
        print('Sunday')    #If there are multiple statements, you can indent from another line
    case _:
        print("Input error")

-----Operation results:
 Enter value: 1
 Monday

 Enter value: 7
 Sunday

 Enter value: 10
 Input error

match is similar to the switch keyword of C language, followed by the variable to be matched; Case is followed by a variety of different conditions, followed by statements to be executed to meet a certain condition; A break statement is not required at the end of each case statement.

The last case underlined indicates the default matching. If the previous conditions do not match, they will run to this case for execution. Similar to the default in C language, the default matching cannot be placed in front of other case statements, otherwise a syntax error error will be reported: wildcard makes remaining patterns unreachable. Of course, the default match is not necessary. Adding a default match can make the results of the program more readable.

Matching data types

Unlike the variable type matched by switch in C language can only be integer or character type, the matching object type in Python can be string type:

#VX: Orange code / juzicode.com
x = input("Enter English abbreviation: ")
match x:
    case 'mon':print('Monday')
    case 'tue':print('Tuesday')
    case 'wed':print('Wednesday')
    case 'thur':print('Thursday')
    case 'fri':print('Friday')
    case 'sat':print('Saturday')
    case 'sun':print('Sunday')
    case _:print("Input error")

-----Operation results:
Enter English abbreviation: sun
 Sunday

Enter English abbreviation: none
 Input error

If floating-point type must be used for matching, it is also possible. In the following example, the variable x to be matched is integer type, and the value after case is integer or floating-point type:

#VX: Orange code / juzicode.com
x = int(input("Enter value: "))
match x:
    case 1:print('Monday')
    case 2:print('Tuesday')
    case 3.0:print('Wednesday')
    case 4.0:print('Thursday')
    case 5.0:print('Friday')
    case 6.0:print('Saturday')
    case 7.0:print('Sunday')
    case _:print("Input error")

-----Operation results:
Enter value: 1
 Monday

Enter value: 3
 Wednesday

Enter value: 9
 Input error

Alternatively, the variable x to be matched is floating-point, and the value after case is integer or floating-point:

#VX: Orange code / juzicode.com
x = float(input("Enter value: "))
match x:
    case 1:print('Monday')
    case 2:print('Tuesday')
    case 3:print('Wednesday')
    case 4:print('Thursday')
    case 5.5:print('Friday')
    case 6:print('Saturday')
    case 7.0:print('Sunday')
    case _:print("Input error")

-----Operation results:
Enter value: 1
 Monday

Enter value: 1.0
 Monday

Enter value: 5.5
 Friday

Enter value: 7.2
 Input error

It can be seen from the above examples that the variable type after match and the type after case do not have to be the same. The experiment designed below is to return different data types by inputting different numerical simulation functions, so that the variable types after match are different. If there is one that can be matched in case, the corresponding print will be output:

#VX: Orange code / juzicode.com
def func():
    x = int(input("Enter value: "))
    if x==1:return 1.0
    elif x==2:return '2'
    elif x==3:return (3,0,1)
    elif x==4:return [4,0,0]
    elif x==5:return {'5':'k','A':1}
    elif x==6:return 6
    elif x==7:return set((7,))
    else:return x

x=func()
print(type(x))
match x:
    case 1.0:print('Monday')
    case '2':print('Tuesday')
    case (3,0,1):print('Wednesday')
    case [4,0,0]:print('Thursday')
    case {'5':'k','A':1}:print('Friday')
    case 6:print('Saturday')
    case set((7,)):print('Sunday')
    case _:print("Input error")

-----Operation results:
Enter value: 0
<class 'int'>
Input error

Enter value: 1
<class 'float'>
Monday

Enter value: 2
<class 'str'>
Tuesday

Enter value: 3
<class 'tuple'>
Wednesday

Enter value: 4
<class 'list'>
Thursday

Enter value: 5
<class 'dict'>
Friday

Enter value: 6
<class 'int'>
Saturday

Enter value: 7
<class 'set'>
Input error

As can be seen from the above example, the match case data types (object types) in Python are rich and colorful. They can be integers, floating-point numbers, tuples, lists and dictionaries. However, for the set type, even if it seems that the values are the same, they are not matched successfully.

Multi condition matching

After talking about the types of matching variables, let's take a look at multi condition matching.

We know that in C language, if you want to match multiple conditions, you can write case statements side by side without break statements. For example, in the following example, enter 1 ~ 5 matching working days and 6 ~ 7 matching weekends:

    switch(x){
        case 1:  
        case 2:  
        case 3: 
        case 4: 
        case 5: printf("weekdays\n"); break;
        case 6:  
        case 7: printf("weekend\n"); break;
        default:printf("Input error\n"); break;
    }

When x is any one of 1, 2, 3, 4 and 5, printf("working day \ n") can be matched to achieve multi condition matching.

Let's see if it is possible to match multiple conditions in Python:

#VX: Orange code / juzicode.com
x = int(input("Enter value: "))
match x:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:print('weekdays')
    case 6: 
    case 7:print('weekend')
    case _:print("Input error")

-----Operation results:
    case 2:
    ^
IndentationError: expected an indented block after 'case' statement on line 4

I'm sorry to prompt that the indentation error is wrong. It can't be written like this in Python!

Python's match case statement should use logic or symbol (|) to represent multi condition matching. case condition1 | condition2 | condition3 |...:

#VX: Orange code / juzicode.com
x = int(input("Enter value: "))
match x:
    case 1 | 2 | 3 | 4 | 5:
        print('weekdays')
    case 6 | 7: 
        print('weekend')
    case _:
        print("Input error")

-----Operation results:
Enter value: 1
 weekdays
 
Enter value: 5
 weekdays

Enter value: 6
 weekend

Enter value: 7
 weekend

Enter value: 8
 Input error

Be careful not to use or instead of logic or symbols, otherwise SyntaxError will be prompted:

    case 6 or 7:
           ^^
SyntaxError: expected ':'

Wildcard matching

The match case statement also supports wildcard matching. Wildcard matching similar to match x:case [cond1,cond2,..., * rem] can be used. As long as the values and order of the first few elements of the list or tuple meet cond1,cond2,..., the remaining elements, no matter how many, can meet the matching conditions, and rem represents the list composed of the remaining elements. The conditions here are not necessarily multiple like cond1,cond2,... Or there can be only one cond1. In the following example, enter different values and return lists of different lengths. The matching condition is [1,*rem]. As long as the 0th element of the matched object is 1, it can be matched:

#VX: Orange code / juzicode.com
def func():
    x = int(input("Enter value: "))
    if x==0: return [0,1]
    elif x==1: return [1]
    elif x==2: return [1,2]
    elif x==3: return [1,2,3]
    else: return None

x=func()
print('x:',x)
match x:
    case [1,*rem]:
        print('rem:',rem)      
    case _:
        print("Unmatched")

-----Operation results:
Enter value: 0
x: [0, 1]
Unmatched   ###### The 0th element of x is 0, which does not meet the requirement that the 0th element in the matching criteria is 1
        
Enter value: 1
x: [1]
rem: []  ###### The 0th element of x is 1, which meets the matching condition. Because there is only 1 element, rem is empty

Enter value: 2
x: [1, 2]
rem: [2] ###### The 0th element of x is 1, which meets the matching conditions, and rem is the list composed of the remaining elements

Enter value: 3
x: [1, 2, 3]
rem: [2, 3]

Enter value: 5
x: None  
Unmatched  ###### The x value is None and cannot be matched

Tuples can also be matched with wildcards. We change the above example x to tuple type. The case matching object is also tuple type. Other conditions remain unchanged. You can see that the matching method is the same as that of list type. However, it should be noted that if it can be matched, rem will still get a list type instead of tuple type:

#VX: Orange code / juzicode.com
def func():
    x = int(input("Enter value: "))
    if x==0: return (0,1)
    elif x==1: return (1,)
    elif x==2: return (1,2)
    elif x==3: return (1,2,3)
    else: return None

x=func()
print('x:',x)
match x:
    case (1,*rem):
        print(type(rem),'rem:',rem)      
    case _:
        print("Unmatched")

-----Operation results:
Enter value: 3
x: (1, 2, 3)
<class 'list'> rem: [2, 3] ###Although the matching object is tuple, rem still gets a list
 
Enter value: 1
x: (1,)
<class 'list'> rem: []

In addition to the single asterisk wildcard, you can also use the double asterisk wildcard. The double asterisk wildcard can be used for some key value matching in the dictionary. For example, in the following example, as long as the case matching object has a pair of key values of {2: "Tuesday"}, it can be matched, and the value of rem can be obtained as the remaining key values.

#VX: Orange code / juzicode.com
def func():
    x = int(input("Enter value: "))
    if x==0: return {1: "Monday"}
    elif x==1: return {2: "Tuesday"}
    elif x==2: return {1: "Monday", 2: "Tuesday"}
    elif x==3: return {1: "Monday", 2: "Tuesday",3:'Wednesday'}
    else: return None

x=func()
print('x:',x)
match x: 
    case {2: "Tuesday", **rem}:
        print('rem:',rem) 
    case _:
        print('Unmatched')

-----Operation results:
Enter value: 0
x: {1: 'Monday'}  
Unmatched       ######Does not contain {2: 'Tuesday'}, so there is no match

Enter value: 1
x: {2: 'Tuesday'}
rem: {}     #####Can match, and rem is an empty dictionary {}

Enter value: 2
x: {1: 'Monday', 2: 'Tuesday'}
rem: {1: 'Monday'}  ##### Remove the key value {2: 'Tuesday'} and assign the remaining key value {1: 'Monday'} to rem

Enter value: 3
x: {1: 'Monday', 2: 'Tuesday', 3: 'Wednesday'}
rem: {1: 'Monday', 3: 'Wednesday'}

Enter value: 10
x: None   
Unmatched  ##### The x value is None and cannot be matched

Here we introduce the basic usage, matching data types, multi condition matching and wildcard matching of match case statements in python. In addition to these contents, match case statements also include object structure matching, conditional matching, sub pattern matching, etc. if you want to try more match case examples, you can visit PEP636: PEP 636 -- Structural Pattern Matching: Tutorial | Python.org

Topics: Python