条件语句 if/elif/else

程序的第一层复杂性来自”做选择”:判断用户是不是成年、订单是不是超时、密码是不是正确……这些都需要条件语句。Python 用 if / elif / else 完成这件事,同时还有一个 Python 3.10+ 的现代化补充:match/case(模式匹配)。这一篇把两种写法都讲透,让你知道什么时候用什么。

一、if 的基本形式

Python 条件语句最基本的形式:

1
2
3
4
age = int(input("年龄:"))

if age >= 18:
print("成年")

注意四件事:

  1. if 后面跟条件,条件后紧跟一个冒号 :
  2. 缩进 4 空格表示”属于 if 的代码块”;
  3. 条件不需要括号(if (age >= 18): 语法上合法但不推荐);
  4. 不用大括号,缩进就是分隔。

二、if / else

选择的两条分支:

1
2
3
4
5
6
age = int(input("年龄:"))

if age >= 18:
print("成年")
else:
print("未成年")

三、if / elif / else

超过两条分支时用 elif(else if 的缩写):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
score = int(input("分数:"))

if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
elif score >= 60:
grade = "D"
else:
grade = "F"

print(f"等级 {grade}")
  • elif 可以有任意多个;
  • else 是可选的,最多一个;
  • 一旦某条分支匹配就退出,后续分支不再检查。

四、条件里的”真”与”假”

前面 变量与基本数据类型 讲过:Python 里以下都视为

  • FalseNone
  • 数值 00.0
  • 空字符串 ""、空列表 []、空字典 {}、空集合 set()

其他一切都是。所以:

1
2
3
4
5
6
7
8
9
10
name = input("名字:")

if name: # ✅ Pythonic
print(f"你好,{name}")
else:
print("你没输入名字")

# ❌ 冗长
if name != "":
print(...)

自定义对象可以通过 __bool____len__ 方法自定义真值行为,这个后面 特殊方法(魔术方法) 会讲。

五、复合条件:and / or / not

多个条件组合:

1
2
3
4
5
6
7
8
9
10
11
12
age = 25
has_ticket = True
is_vip = False

if age >= 18 and has_ticket:
print("可以进场")

if is_vip or age >= 65:
print("免排队")

if not has_ticket:
print("买票先")

三个要点:

  1. and or 短路求值A and B 若 A 为假就不算 B;
  2. not 优先级 高于 and / or
  3. 复杂条件加括号更安全:if (a and b) or (c and not d):

六、链式比较(Python 特色)

1
2
3
4
5
6
7
8
9
age = 25

# 好,Python 特有
if 18 <= age < 60:
print("劳动年龄")

# 不好
if age >= 18 and age < 60:
print("劳动年龄")

七、嵌套 if

if 里可以再套 if

1
2
3
4
5
6
7
8
9
10
age = int(input("年龄:"))
has_id = input("有身份证吗?(y/n):") == "y"

if age >= 18:
if has_id:
print("可以办卡")
else:
print("请先办身份证")
else:
print("年龄不足")

嵌套超过 2 层就要考虑重构——通常改成”提前 return”或者合并条件:

1
2
3
4
5
6
7
# 更清爽
if age < 18:
print("年龄不足")
elif not has_id:
print("请先办身份证")
else:
print("可以办卡")

在函数里更常见 “early return“ 风格:

1
2
3
4
5
6
def apply_card(age: int, has_id: bool) -> str:
if age < 18:
return "年龄不足"
if not has_id:
return "请先办身份证"
return "可以办卡"

这种”守卫式返回”能显著降低嵌套复杂度。

八、条件表达式(三元)

前面 运算符与表达式 讲过:

1
2
3
4
label = "成年" if age >= 18 else "未成年"

# 常用于生成列表元素
tags = ["young" if a < 18 else "adult" for a in ages]

九、match / case:Python 3.10+ 的模式匹配

match 是 Python 3.10 引入的重量级语法,功能比 C/Java 的 switch 强得多。它匹配的不是”值”,而是”结构”。

基础用法(当增强版 switch)

1
2
3
4
5
6
7
8
9
10
11
12
def http_status(code: int) -> str:
match code:
case 200:
return "OK"
case 301 | 302: # 或匹配
return "Redirect"
case 400 | 401 | 403 | 404:
return "Client Error"
case 500:
return "Server Error"
case _: # 通配,等价于 default
return "Unknown"

case _ 是通配符,一定放在最后,作用等同于 else

结构匹配(真正强大的地方)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def describe_point(point: tuple) -> str:
match point:
case (0, 0):
return "原点"
case (0, y):
return f"Y 轴上,y={y}"
case (x, 0):
return f"X 轴上,x={x}"
case (x, y):
return f"点 ({x}, {y})"
case _:
return "不是坐标"

print(describe_point((0, 0))) # 原点
print(describe_point((5, 0))) # X 轴上,x=5
print(describe_point((3, 4))) # 点 (3, 4)

匹配字典 / 类

1
2
3
4
5
6
7
8
9
10
11
12
13
def handle_event(event: dict) -> str:
match event:
case {"type": "click", "x": x, "y": y}:
return f"点击 ({x}, {y})"
case {"type": "keydown", "key": key}:
return f"按键 {key}"
case {"type": t}:
return f"未知事件 {t}"
case _:
return "格式不对"

print(handle_event({"type": "click", "x": 10, "y": 20})) # 点击 (10, 20)
print(handle_event({"type": "keydown", "key": "Enter"})) # 按键 Enter

带守卫的 case

1
2
3
4
5
6
7
8
9
10
def category(age: int) -> str:
match age:
case n if n < 0:
return "非法"
case n if n < 18:
return "未成年"
case n if n < 60:
return "成年"
case _:
return "老人"

match vs if-elif

  • 简单值比较:if-elif 就够,match 反而啰嗦;
  • 结构匹配(元组解构、字典模式、类模式):match 优雅得多;
  • 顺序执行:match 只匹配第一个符合的 case,且不会 fall through(不用写 break)。

Python 3.9 及更早版本不能用 match,必须用 if-elif。

十、一个综合例子:石头剪刀布

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# rps.py
"""石头剪刀布,展示 if 与 match 的组合。"""

import random


def get_computer_choice() -> str:
return random.choice(["石头", "剪刀", "布"])


def get_user_choice() -> str:
while True:
raw = input("请出招(石头/剪刀/布/quit):").strip()
if raw == "quit":
return raw
if raw in {"石头", "剪刀", "布"}:
return raw
print("请输入正确选项")


def judge(user: str, computer: str) -> str:
if user == computer:
return "平局"
# 用 match 表达"什么克什么"
match user:
case "石头":
return "赢" if computer == "剪刀" else "输"
case "剪刀":
return "赢" if computer == "布" else "输"
case "布":
return "赢" if computer == "石头" else "输"
case _:
return "非法"


def main():
score = {"赢": 0, "输": 0, "平局": 0}
while True:
user = get_user_choice()
if user == "quit":
break
computer = get_computer_choice()
result = judge(user, computer)
score[result] += 1
print(f"电脑:{computer},结果:{result}")

print(f"总战绩:{score}")


if __name__ == "__main__":
main()

十一、常见陷阱

  1. 忘记冒号if age >= 18 忘写 : 会立即报 SyntaxError。
  2. 缩进不一致:Tab 混空格会报 IndentationError;建议 IDE 里配置”Tab = 4 空格”。
  3. if x == True:多此一举。直接 if x:
  4. if x == None:应该用 if x is None
  5. 在条件里赋值:Python 3.8 之前不允许,3.8 起用海象 :=,别把 === 搞混:if x = 5: 是语法错误,好事。
  6. elif 之间条件重叠if x > 10: ... elif x > 5: ... 中,只会命中第一个匹配的分支。
  7. match 里 case 常量名 陷阱case foo: 会把 foo 当作新绑定的变量名而不是常量。要匹配已有常量,加上模块前缀:case Color.RED: 或者比较值 case _ if x == FOO:
1
2
3
4
5
FOO = 1
def f(x):
match x:
case FOO: # 陷阱!FOO 被当成新变量,永远匹配
return "matched"

正确写法:

1
2
3
4
5
6
7
8
from enum import Enum
class Color(Enum):
RED = 1

def f(c):
match c:
case Color.RED: # 带点号的名字才被识别为常量匹配
return "red"

十二、小结与延伸阅读

  • 基本形式:if / elif / else,注意冒号和缩进;
  • 空容器、0、None 都是假;直接 if x: 判空最 Pythonic;
  • 链式比较 18 <= age < 60
  • 复杂条件加括号,避免优先级坑;
  • 嵌套超 2 层考虑 early return;
  • 三元表达式 A if cond else B
  • Python 3.10+ 用 match/case 做结构匹配;
  • match 里的常量必须带前缀,否则被当成变量绑定。

延伸阅读:

下一篇 循环语句 for 与 while 我们要让程序开始”重复干活”。