Python 的这个 match case 语法是 3.10 新出的,旧版不支持。其本质上与 Java 和 Go 的 switch case,或 Ruby 的 case when 没什么区别。

原本 if-elif-else 用得好好的,而且设计团队一开始也没想着再搞个重复功能的东西出来(不然一开始设计肯定就加了,也不至于这么千呼万唤始出来),奈何扛不住广大开发者的强烈要求,终于出了个 match case。match 语句在某些情况下更加简洁和高效。在需要处理多个条件时,match 语句也可以通过一定的方法进行优化。正如青钢影的台词一般:优雅,永不过时。

语法特点

为什么不是 switch case (比如 Go)语法?

switch 只能分流整型、枚举值等 基本类型的离散值。match 除了 switch 的功能外,还可以匹配对象、条件等,是更复杂的模式匹配,功能更强大

注意:match case 不支持 fall-through,每个 case 里边都相当于默认有个 break 语句,始终只会匹配进入到最近的一个 case。

传统 if else 语句

score = 'B'

if score == 'A':
    print('Score is A')
elif score == 'B':
    print('Score is B')  # Score is B
elif score == 'C':
    print('Score is C')
else:
    print('Invalid Score')

新的 match case 语法

精确匹配

只精确匹配某一个值

score = 'B'

match score:
    case 'A':
        print('Score is A')
    case 'B':
        print('Score is B')  # Score is B
    case 'C':
        print('Score is C')
    case _:
        print('Invalid Score')

通配符

其中的 case _ 通配符类似于 else,需要放到最后,不然语法上会报错。

score = 'B'

match score:
    case 'A':
        print('Score is A')
    case 'B':
        print('Score is B')
    case _:  # SyntaxError: wildcard makes remaining patterns unreachable
        print('Invalid Score')
    case 'C':
        print('Score is C')

其实,这种不加任何守卫条件的单个变量匹配都属于通配,当然,通配的变量不一定非得是 _,一般通配变量遵守这种规范——如果通配变量你不再使用,则用 _ 即可;如果还需要使用,则使用自定义的变量。

大家可能会疑问:case 'A' 为什么不属于通配呢?这是因为 case 'A' 其实是 case _ if score == 'A' 的简写,本质上是有守卫条件的。

多值匹配

可使用 | 来同时匹配多个可能的值

score = 'B'

match score:
    case 'A':
        print('Score is A')
    case 'B' | 'C':
        print('Score is B or C')  # Score is B or C
    case 'D':
        print('Score is D')
    case _:
        print('Invalid Score')

守卫条件

我们可以在匹配时添加限定的守卫条件

score = 80

match score:
    case _ if score >= 90:
        print('Score is A')
    case _ if 90 > score >= 80:
        print('Score is B')  # Score is B
    case _ if 80 > score >= 70:
        print('Score is C')
    case _ if 70 > score >= 60:
        print('Score is C')
    case _:
        print('Invalid Score')

匹配并赋值

匹配并将匹配结果赋值给新变量

point = (3, 3)

match point:
    case (0, 0):
        print('Point at Origin')
    case (x, y) if x == y:
        print(f'Point on the line y = x')  # Point on the line y = x
    case (x, y):
        print(f'Point at ({x}, {y})')

模式匹配

有时候,我们希望只有满足指定模式的才能匹配上,比如,我想将二维平面的点和三维平面的点匹配分开。这样,只有满足指定模式的才能匹配上。

注意:单个变量可匹配任意模式,也即上面所说的通配,所以要放到最后进行匹配。

point = (1, 2, 3)
match point:
    case (x, y):
        print(f'the match is flat Point')
    case (x, y, z):
        print(f'the match is space Point')  # the match is space Point
    case x:
        print(f"the match value is {x}")

复杂匹配

复杂的匹配甚至可以将模式匹配,守卫条件和变量赋值合到一块处理。

下面这个例子中,第一个 case 匹配包含特定三个水果的列表;第二个 case 使用守卫语句来匹配包含苹果和另一个特定水果的列表,并将匹配到的另外一种特定水果赋值给 fruit 变量;第三个case 则匹配其他任意水果列表。

fruits = ["apple", "orange"]

match fruits:
    case ["apple", "banana", "orange"]:
        print("All three fruits")
    case ["apple", fruit] if fruit in ["banana", "orange"]:
        print(f"Apple and {fruit}")  # Apple and orange
    case _:
        print("Some other fruits")
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐