CC++ & Algorithm

没有 `break` 的 `switch`,反而更好用了?

如果你从 C 语言或 Java 转过来写 Python,第一次见到 match-case 时,可能会下意识地找 break 在哪。找了一圈没找到,然后心里一紧:这玩意儿会不会“穿透”啊?

放心,Python 的 match-case 不需要 break,它匹配完一个分支就自动退出。这个设计让多路选择代码变得更干净,也更符合直觉。

自助餐模式:端着变量去“打菜”

想象你走进一家自助餐厅,手里端着一个盘子——这个盘子就是你要匹配的变量。餐厅里有一排摊位,每个摊位前面立着牌子,写着对应的菜品编号:

case "A1": 薯片
case "A2": 巧克力
case "A3": 可乐
case _: 无效按钮

你端着 "A2" 走到第一个摊位,厨师看了一眼,不对,不是 A1。再走到第二个摊位,对了,是 A2,厨师给你打了一勺巧克力,然后你就端着盘子走了——不会再去 A3 摊位问“能不能再来点可乐”。

这就是 match-case 的执行逻辑:从上到下逐个匹配,一旦命中,执行对应代码块,然后整段 match 结束。

button = "A2"
match button:
    case "A1":
        print("出货:薯片")
    case "A2":
        print("出货:巧克力")
    case _:
        print("无效按钮")

输出:出货:巧克力

_ 不是变量名,是“万能通行证”

很多初学者会把 case _ 理解成“else”,然后问:那 _ 能不能放在中间?语法上可以,但逻辑上等于给自己挖坑。

来看这道题:

x = 1
match x:
    case 0:
        print("零")
    case 1:
        print("一")
    case _:
        print("其他")

输出是什么?显然是 。因为 case 1 命中了,后面的 _ 根本轮不到。

但如果把 _ 提到前面:

match x:
    case _:
        print("其他")
    case 1:
        print("一")

case 1 永远不可能执行。_ 能匹配任何值,它前面的变量全都会被它截胡。所以,语法上 _ 可以出现在任何位置,但聪明人都把它放在最后。

| 或匹配:给自助餐加个套餐

有时候好几个选项要执行同样的操作,比如判断一个颜色是不是三原色。如果写三个一模一样的 case,那代码就太啰嗦了。match-case 支持用竖线 | 把多个值连起来:

color = "red"
match color:
    case "red" | "yellow" | "blue":
        print("这是三原色之一")
    case _:
        print("其他颜色")

一行搞定三种情况。这个语法特别适合那种“多个输入,一个动作”的场景,比如判断用户输入的命令是不是退出指令:

case "quit" | "exit" | "q":
    print("再见")

别踩的四个坑

  1. 忘写冒号case 1 后面必须有 :,跟 if 一样。
  2. 缩进错位matchcase 对齐,case 下面的代码要再缩进一层。
  3. _ 写成变量_ 是通配符,不是普通变量名,别想着用它来接收值。
  4. Python 版本不够:3.10 以下跑不了,会报 SyntaxError。如果还在用 3.8、3.9,要么升级,要么老老实实用 if-elif-else

什么时候别用 match-case

match-case 很强,但它只能做等值匹配。如果你想判断 x > 5,或者 x % 2 == 0,那还得用 if。别为了显摆新语法而硬用,代码的可读性永远排第一。

举个反面例子:

# 这样写就太别扭了
match x:
    case _ if x > 5:
        print("大于5")
    case _:
        print("小于等于5")

虽然 match-case 支持守卫条件,但对这种简单的比较,if-else 两行就搞定了,何必绕弯子。

顺手看一道判断题

之前看到有同学争论:“下划线 _ 只能放在最后一个 case 作为默认匹配。”这个说法对不对?答案是——不对。

_ 不是 switch 里的 default,它只是一个普通的通配符模式,语法上可以放在任何位置。但放在非末尾会导致后面的 case 永远不可达,所以规范上强烈建议放最后。这道题的考点其实是在区分“语法允许”和“写法合理”,概念搞清楚了,这种题就不会错。

进阶方向

如果你觉得 match-case 只是 switch 的替代品,那你就低估它了。它真正的威力在于结构模式匹配,比如匹配列表、元组、字典,甚至自定义类的属性:

point = (3, 0)
match point:
    case (0, 0):
        print("原点")
    case (x, 0):
        print(f"x轴上的点,x={x}")
    case (0, y):
        print(f"y轴上的点,y={y}")
    case (x, y):
        print(f"普通点:({x}, {y})")

这种能力远超传统的 switch,在做数据解析、命令分发、AST 处理时特别有用。学到这里,才算真正走进了 Python 模式匹配的大门。


关于作者

我是赵老师,持有 NOI 信息学奥赛教练证书,拥有 15 年以上的软件开发经验,从事信息学少儿编程教学已有 8 年时间。

这些年累计帮助 多名 学生通过编程特长升入自己心仪的目标学校。

如果你在编程学习上有任何疑问,欢迎联系我:18620372957(微信同号)

这篇文章对你有帮助吗?

有用 100%没用 0%

想系统学习这个知识点?查看完整知识点 →