程序并不总是按照同一条路线执行。判断账号是否登录、成绩是否及格、文件是否存在,或者用户输入的内容是否有效,都需要根据条件决定接下来执行哪段代码。
思维导图

Python 使用 if、elif 和 else 编写条件分支。这一章会讲它们的基本写法、多个条件的判断顺序、真假值、条件嵌套和条件表达式,最后再介绍 Python 3.10 加入的 match case。

一、最基本的 if 语句
if 用来判断一个条件是否成立。条件为真时,执行缩进后的代码;条件为假时,直接跳过这段代码。
python
age = 20
if age >= 18:
print("已经成年")
运行结果为:
txt
已经成年
一条完整的 if 语句包含下面几部分:
python
if 条件:
条件成立时执行的代码
if后面写条件表达式。- 条件后面要有冒号
:。 - 分支中的代码需要缩进,一般使用四个空格。
如果分支中有多条语句,它们需要保持相同的缩进:
python
score = 85
if score >= 60:
print("考试通过")
print(f"当前成绩:{score}")
print("程序结束")
前两条 print() 属于 if 代码块,最后一条没有缩进,所以无论条件是否成立都会执行。

二、条件表达式
if 后面需要一个能够判断真假的表达式。比较运算是最常见的条件:
python
temperature = 32
if temperature > 30:
print("今天比较热")
常用的比较运算符如下:
| 运算符 | 含义 | 示例 |
|---|---|---|
== |
等于 | score == 100 |
!= |
不等于 | status != "closed" |
> |
大于 | age > 18 |
< |
小于 | price < 100 |
>= |
大于等于 | score >= 60 |
<= |
小于等于 | count <= 10 |
这里容易把赋值运算符 = 和相等比较 == 写混:
python
age = 20 # 把 20 赋值给 age
age == 20 # 判断 age 是否等于 20
if age = 20: 不是合法写法,会直接出现 SyntaxError。
1. 连续比较
Python 支持连续比较,下面两种写法含义相同:
python
score = 85
if score >= 60 and score <= 100:
print("成绩有效,并且已经及格")
python
if 60 <= score <= 100:
print("成绩有效,并且已经及格")
连续比较更接近数学中的写法,不过只适合这种上下界连续判断。几个没有直接顺序关系的条件,还是应该使用逻辑运算符连接。
2. 成员判断
in 和 not in 也可以直接作为条件:
python
role = "editor"
if role in ("admin", "editor"):
print("允许编辑")
字符串也支持成员判断:
python
filename = "report.pdf"
if ".pdf" in filename:
print("文件名中包含 .pdf")
如果要判断文件的扩展名,使用 endswith() 会更准确:
python
if filename.lower().endswith(".pdf"):
print("这是 PDF 文件")
3. 判断 None
判断变量是否为 None 时,一般使用 is:
python
result = None
if result is None:
print("暂时没有结果")
判断普通数字、字符串和列表的内容时使用 ==,不要把 is 当成另一种相等比较。
三、使用 else 处理另一种情况
只有一个 if 时,条件不成立就不会执行分支中的代码。如果两种情况都需要处理,可以增加 else:
python
age = 16
if age >= 18:
print("可以注册")
else:
print("年龄未满 18 岁")
else 后面不写条件,因为它表示前面的条件不成立时剩下的情况。
下面这个例子判断一个数字是偶数还是奇数:
python
number = 7
if number % 2 == 0:
print("偶数")
else:
print("奇数")
一个整数除以 2 的余数只可能是 0 或 1,所以这里使用 if else 可以覆盖全部情况。
四、使用 elif 判断多个分支
需要判断三种或者更多情况时,可以在 if 和 else 之间加入 elif:
python
score = 85
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
elif score >= 60:
grade = "D"
else:
grade = "E"
print(f"等级:{grade}")
Python 会从上到下检查这些条件。遇到第一个成立的分支以后,就执行对应代码,后面的分支不会继续判断。
在这个例子中,85 不满足 score >= 90,但是满足 score >= 80,所以结果为 B。
1. 条件顺序会影响结果
如果把范围较宽的条件写在前面,后面的条件可能永远没有机会执行:
python
score = 95
# 顺序错误
if score >= 60:
grade = "及格"
elif score >= 90:
grade = "优秀"
95 已经满足第一个条件,所以程序得到的是 及格。这种分段判断一般要按照从严格到宽松,或者从小到大的连续区间排列。
2. else 不是必需的
if 后面可以有多个 elif,最后不一定要写 else:
python
command = "start"
if command == "start":
print("启动任务")
elif command == "stop":
print("停止任务")
elif command == "status":
print("查看状态")
如果 command 不属于这三种情况,程序就跳过整个分支。是否需要 else,要看剩余情况要不要处理。

五、多个 if 与 if elif 的区别
连续写多个 if 时,每个条件都会独立判断:
python
score = 95
if score >= 60:
print("考试通过")
if score >= 90:
print("成绩优秀")
两个条件都成立,所以两句话都会输出。
改成 if elif 以后,只会执行第一个成立的分支:
python
score = 95
if score >= 60:
print("考试通过")
elif score >= 90:
print("成绩优秀")
这次只会输出 考试通过。后面的 elif 并不会继续判断。
因此,如果几件事可以同时发生,就使用多个 if。如果多个分支互相排斥,只需要从中选择一个,就使用 if elif else。
例如,一个订单可以同时满足会员优惠和满减活动,这两个条件可能要分别判断:
python
price = 300
is_member = True
if is_member:
price *= 0.9
if price >= 200:
price -= 20
print(f"实付金额:{price:.2f} 元")
这里第二个判断使用的是会员折扣后的金额。实际业务中折扣顺序会影响结果,所以规则和执行顺序需要先确定清楚。
六、使用逻辑运算符组合条件
一个分支经常需要同时检查多个条件,可以使用 and、or 和 not。
1. and
and 两边都为真时,整个条件才为真:
python
age = 20
has_ticket = True
if age >= 18 and has_ticket:
print("允许入场")
2. or
or 两边只要有一个为真,整个条件就为真:
python
role = "editor"
if role == "admin" or role == "editor":
print("允许修改内容")
判断一个变量是否等于多个候选值时,也可以使用成员判断,代码会更短:
python
if role in ("admin", "editor"):
print("允许修改内容")
下面这种写法是错误的:
python
# 错误写法
if role == "admin" or "editor":
print("允许修改内容")
非空字符串 "editor" 本身就是真值,所以这个条件几乎总会成立。
3. not
not 会把真假结果反过来:
python
is_disabled = False
if not is_disabled:
print("账号可以使用")
4. 运算优先级
not 的优先级高于 and,and 又高于 or。条件比较长时,不要只依赖优先级,使用括号会更容易检查:
python
age = 20
is_member = False
has_invitation = True
if age >= 18 and (is_member or has_invitation):
print("允许参加活动")

七、Python 中的真值与假值
if 后面不一定要写比较表达式。Python 会把对象转换成布尔值,再决定条件是否成立。
下面这些值会被当成 False:
FalseNone- 数字
0、0.0、0j - 空字符串
"" - 空列表
[] - 空元组
() - 空字典
{} - 空集合
set()
其他大多数对象会被当成 True。
python
name = "Ivan"
if name:
print("姓名不为空")
上面的写法相当于:
python
if name != "":
print("姓名不为空")
判断列表是否有内容时也经常这样写:
python
items = ["Python", "Java"]
if items:
print("列表中有数据")
else:
print("列表为空")
1. 字符串 "False" 仍然是真值
字符串里的文字不会自动变成布尔值:
python
print(bool("False"))
print(bool("0"))
print(bool(""))
输出结果为:
txt
True
True
False
前两个字符串中都有字符,所以结果是 True。读取配置或用户输入时,不能直接使用 bool(text) 解析文字形式的真假值,可以自己写出允许的内容:
python
value = "false"
is_enabled = value.strip().lower() in ("true", "1", "yes", "on")
print(is_enabled)
2. None 和空值的含义不同
None 通常表示没有结果或者尚未设置,空字符串和空列表则表示有这个值,只是内容为空。在某些程序里它们可以使用相同的处理方式,但含义并不完全一样:
python
result = None
if result is None:
print("还没有查询")
elif not result:
print("已经查询,但是结果为空")
else:
print("查询到了内容")

八、短路计算
逻辑运算符会按照需要决定是否继续计算右侧表达式。
and 左侧已经为假时,整个结果一定为假,所以右侧不会执行:
python
number = 0
if number != 0 and 10 / number > 2:
print("条件成立")
由于 number != 0 为 False,10 / number 不会执行,因此不会出现除零错误。
or 左侧已经为真时,整个结果一定为真,右侧也不会执行:
python
is_admin = True
if is_admin or check_permission():
print("允许访问")
这里假设 check_permission() 是一个权限检查函数。is_admin 已经为真时,这个函数不会被调用。
短路计算可以避免不必要的操作,不过不要为了省几行代码,把有副作用的函数调用藏在很长的条件中。条件本身应该能够让人直接看懂。
九、嵌套条件判断
一个分支内部还可以继续写 if,这种结构称为嵌套条件:
python
is_login = True
role = "admin"
if is_login:
print("已经登录")
if role == "admin":
print("进入管理页面")
else:
print("进入普通用户页面")
else:
print("请先登录")
内层代码需要再增加一级缩进。嵌套两三层还能看懂,层级继续增加以后,判断关系会变得很乱。
有些嵌套可以合并成一个条件:
python
if is_login and role == "admin":
print("进入管理页面")
不过这两种写法不一定完全等价。前一个例子还需要分别处理未登录和普通用户,合并以后只保留了管理员这一种情况。是否合并,要看每个分支是不是还有自己的处理逻辑。

十、提前结束,减少嵌套
在函数中遇到不满足条件的情况,可以使用 return 提前结束函数。这样通常比不断增加 else 更容易读:
python
def get_discount_price(price, is_member):
if price <= 0:
return 0
if not is_member:
return price
return price * 0.9
如果不提前返回,也可以写成:
python
def get_discount_price(price, is_member):
if price <= 0:
result = 0
else:
if not is_member:
result = price
else:
result = price * 0.9
return result
第二种写法没有语法问题,但是多了一层嵌套。函数内容变长以后,提前处理异常情况和边界情况会更清楚。函数和 return 会在后面的章节中详细讲,这里先理解这种写法为什么能够减少层级。
十一、条件表达式
如果只是根据一个条件在两个值之间选择,可以使用条件表达式:
python
age = 20
message = "成年" if age >= 18 else "未成年"
print(message)
它的基本结构是:
python
条件成立时的值 if 条件 else 条件不成立时的值
条件表达式适合简单赋值。如果两个分支各有多条语句,还是使用普通的 if else:
python
score = 85
if score >= 60:
print("考试通过")
print(f"当前成绩:{score}")
else:
print("考试未通过")
print("需要参加补考")
不要连续嵌套多个条件表达式。虽然语法允许,但是读起来比普通分支更费劲。
十二、空代码块与 pass
Python 的代码块不能为空。如果暂时还没有想好分支中的内容,可以使用 pass 占位:
python
status = "pending"
if status == "pending":
pass
else:
print("任务已经处理")
pass 不会执行任何操作,它只保证当前代码块在语法上完整。后面补上正式代码以后,应该把它删除。
十三、使用 match case 匹配固定分支
Python 3.10 加入了 match case。当程序需要根据同一个值匹配多个固定分支时,它有时会比一长串 elif 更清楚:
python
command = "status"
match command:
case "start":
print("启动任务")
case "stop":
print("停止任务")
case "status":
print("查看状态")
case _:
print("未知命令")
case _ 用来接收前面都没有匹配到的情况,作用有点像 else。
1. 同时匹配多个值
竖线 | 可以把几个候选值放在同一个分支:
python
method = "GET"
match method:
case "GET" | "HEAD":
print("读取请求")
case "POST" | "PUT":
print("写入请求")
case _:
print("其他请求")
2. 解构序列
match case 还能按照数据结构匹配内容:
python
point = (10, 0)
match point:
case (0, 0):
print("原点")
case (x, 0):
print(f"X 轴上的点:{x}")
case (0, y):
print(f"Y 轴上的点:{y}")
case (x, y):
print(f"普通坐标:{x}, {y}")
这里的 x 和 y 会接收匹配位置上的值。它已经不只是其他语言中常见的 switch,还包含结构模式匹配的能力。
对于简单的真假条件和范围判断,if elif else 仍然更直接。match case 更适合同一个对象有多种固定形式,或者需要根据结构拆出数据的情况。

十四、综合示例:计算订单实付金额
下面的程序根据订单金额、会员状态和优惠码计算实付金额。为了方便查看条件执行顺序,例子没有把逻辑拆成函数:
python
amount = float(input("请输入订单金额:"))
member_text = input("是否为会员(yes/no):").strip().lower()
coupon = input("请输入优惠码,没有则直接回车:").strip().upper()
if amount <= 0:
print("订单金额必须大于 0")
else:
is_member = member_text in ("yes", "y")
if is_member:
amount *= 0.9
if coupon == "SAVE20" and amount >= 100:
amount -= 20
elif coupon:
print("优惠码无效或者未达到使用金额")
shipping_fee = 0 if amount >= 99 else 8
total = amount + shipping_fee
print(f"商品金额:{amount:.2f} 元")
print(f"运费:{shipping_fee:.2f} 元")
print(f"实付金额:{total:.2f} 元")
如果输入:
bash
请输入订单金额:150
是否为会员(yes/no):yes
请输入优惠码,没有则直接回车:SAVE20
会员折扣后金额为 135 元,继续满足优惠码条件,再减去 20 元。由于最后金额仍然超过 99 元,所以免运费,输出结果为:
商品金额:115.00 元
运费:0.00 元
实付金额:115.00 元
这个例子中会员折扣和优惠码可以同时生效,所以使用了两个独立的 if。优惠码无效和没有输入优惠码的处理又不同,因此第二个判断中使用了 elif coupon。
十五、常见错误
1. 忘记写冒号
python
# 错误写法
if score >= 60
print("考试通过")
条件后面缺少冒号,会出现 SyntaxError。
2. 缩进不一致
python
# 错误写法
if score >= 60:
print("考试通过")
print("成绩有效")
同一个代码块必须保持相同缩进,不要混用不同数量的空格和制表符。
3. 把 = 写成判断条件
python
# 错误写法
if status = "done":
print("任务完成")
相等比较应该使用 ==:
python
if status == "done":
print("任务完成")
4. elif 顺序写反
python
score = 95
# 范围较宽的条件挡住了后面的分支
if score >= 60:
print("及格")
elif score >= 90:
print("优秀")
这类范围判断需要检查每一个边界值,尤其是 59、60、89、90 和 100 这些刚好位于区间边缘的值。
5. 错误使用 or
python
# 错误写法
if role == "admin" or "editor":
print("允许访问")
应该完整比较两次,或者直接使用成员判断:
python
if role == "admin" or role == "editor":
print("允许访问")
if role in ("admin", "editor"):
print("允许访问")
6. 把多个独立条件写成 elif
如果一个订单能够同时使用两项优惠,第二项就不能写成 elif,否则第一项成立以后,第二项不会继续判断。
7. 条件嵌套太深
嵌套层级太多时,可以把边界情况提前处理,或者把一部分判断拆成函数。不要为了追求代码行数少,把所有条件挤在一个表达式里。
十六、练习
练习一:判断数字
接收用户输入的整数,判断它是正数、负数还是零。
练习二:成绩等级
接收 0 到 100 之间的成绩,按照下面的规则输出等级:
| 成绩范围 | 等级 |
|---|---|
| 90~100 | A |
| 80~89 | B |
| 70~79 | C |
| 60~69 | D |
| 0~59 | E |
输入不在 0 到 100 范围内时,输出 成绩无效。
练习三:闰年判断
接收一个年份。能够被 400 整除,或者能够被 4 整除但不能被 100 整除的年份是闰年。
练习四:简单登录判断
预设用户名和密码,接收用户输入。用户名和密码都正确时输出 登录成功;用户名不存在时输出 用户不存在;用户名正确但密码错误时输出 密码错误。
练习五:票价计算
根据年龄计算票价:6 岁以下免费,6~17 岁半价,18~59 岁全价,60 岁及以上半价。再增加一个会员条件,会员可以在计算后的票价上继续打九折。
练习六:命令匹配
使用 match case 处理 start、stop、status 和 help 四个命令,其他输入统一输出 未知命令。
这一章讲完以后,程序已经可以根据输入选择不同的执行路线。下一章会继续讲循环,包括 while、for、range()、break 和 continue。