10. 使用条件表达式(if-else 表达式)
在第 8 章中,我们学习了如何使用 if 语句在程序中做决策。这些语句允许我们根据条件执行不同的代码块。然而,有时我们需要在两个值之间做选择,而不是在两个代码块之间做选择。Python 为这种常见场景提供了一种特殊语法:条件表达式。
条件表达式(在其他语言中也称为 三元表达式(ternary expressions) 或 三元运算符(ternary operator))让我们在只需要根据条件选择一个值或另一个值时,编写更紧凑的决策代码。它们在赋值以及构建更大的表达式时尤其有用。
10.1) 条件表达式是什么
条件表达式(conditional expression) 是一个单一的表达式,它会根据条件求值为两个值之一。与控制哪个代码块执行的 if 语句不同,条件表达式会产生一个可以立即使用的值。
我们来看一个常见场景。假设我们正在编写一个程序,按年龄对学生进行分类:
# 使用 if 语句(我们已经知道的方式)
age = 16
if age >= 18:
category = "adult"
else:
category = "minor"
print(f"Category: {category}") # Output: Category: minor这完全可行,但请注意,我们实际上只是从两个字符串值中选择一个。对于这样一个简单的决策,这种结构有点啰嗦。下面是使用条件表达式实现的相同逻辑:
# 使用条件表达式
age = 16
category = "adult" if age >= 18 else "minor"
print(f"Category: {category}") # Output: Category: minor两种写法产生的结果完全相同,但条件表达式更紧凑。它会根据条件,直接把两个值中的一个赋给 category。
理解根本差异
关键区别在于:条件表达式是表达式,而不是语句:
- 表达式(expression) 是会求值为某个值的东西。你可以在任何需要值的地方使用它:在赋值中、作为函数参数、放在其他表达式内部等。
- 语句(statement) 是一条完整的指令,用来执行某个动作,但不会产生一个值。
# 这是一个表达式 —— 它会产生一个值
result = 10 if True else 20
# 这是一个语句 —— 它会执行动作,但本身不是一个值
if True:
result = 10
else:
result = 20因为条件表达式会产生值,所以在某些情况下它们更灵活。不过,这并不意味着它们总是更好——我们会在本章后面探讨何时应使用每种方式。
10.2) if–else 表达式的语法
条件表达式的语法遵循如下模式:
value_if_true if condition else value_if_false我们来拆解每个组成部分:
value_if_true:当条件为True时,会被求值并返回的表达式if:引入条件的关键字condition:决定返回哪个值的布尔表达式else:引入备选值的关键字value_if_false:当条件为False时,会被求值并返回的表达式
注意:如果你熟悉其他编程语言,这个顺序可能看起来有点不寻常。在 Python 中,“为真时的值”放在最前面,然后是条件,最后是“为假时的值”。这种顺序读起来有点像自然英语:“如果条件为真就给我 X,否则给我 Y。”
我们来看一些使用不同类型值的例子:
# 示例 1:在数字之间选择
temperature = 25
comfort_level = "warm" if temperature > 20 else "cool"
print(comfort_level) # Output: warm
# 示例 2:在计算结果之间选择
score = 85
bonus = 10 if score >= 90 else 5
print(f"Bonus points: {bonus}") # Output: Bonus points: 5
# 示例 3:在布尔值之间选择
has_permission = True
access = "granted" if has_permission else "denied"
print(f"Access: {access}") # Output: Access: granted
# 示例 4:条件可以是任意布尔表达式
username = "admin"
role = "administrator" if username == "admin" else "regular user"
print(f"Role: {role}") # Output: Role: administrator重要语法说明
在条件表达式中,else 部分是必需的。与 if 语句中 else 可选不同,你必须同时提供两种备选:
# 这是无效的 —— 缺少 else
# result = "yes" if True # SyntaxError
# 这是有效的 —— 两个分支都提供了
result = "yes" if True else "no"这个要求很合理,因为表达式必须总是产生一个值。如果条件为 False 且没有 else 子句,那么表达式应该产生什么值呢?Python 要求你对两种可能都写清楚。
10.3) 条件表达式如何求值
理解 Python 如何对条件表达式求值,有助于你编写正确的代码并预测程序行为。求值遵循一套明确且可预测的顺序。
求值过程
Python 会按如下顺序对条件表达式求值:
- 求值条件(
if后面的布尔表达式) - 根据结果:
- 如果条件为
True,则求值并返回value_if_true - 如果条件为
False,则求值并返回value_if_false
- 如果条件为
关键点是,Python 只会求值两个值表达式中的一个,而不是两个都求值。这称为短路求值(short-circuit evaluation),它与 and 和 or 运算符的工作方式类似(我们在第 9 章学过)。
# 只会对相关分支求值
x = 10
result = x * 2 if x > 5 else x / 2
# 因为 x > 5 为 True,Python 会计算 x * 2(得到 20)
# 并且永远不会计算 x / 2
print(result) # Output: 20为什么短路求值很重要
短路求值可以防止错误并提高效率:
# 示例 1:避免除以零
denominator = 0
result = "undefined" if denominator == 0 else 100 / denominator
print(result) # Output: undefined
# 因为条件为 True,所以永远不会尝试执行 100 / denominator
# 从而避免 ZeroDivisionError# 示例 2:避免对 None 执行操作
data = None
length = 0 if data is None else len(data)
print(length) # Output: 0
# 因为 data 是 None,所以永远不会调用 len(data)
# 从而避免 TypeError条件表达式中的真值性
与 if 语句(第 8 章)一样,条件表达式中的条件也使用 Python 的真值性规则。任何值都可以作为条件:
# 空字符串为假值
name = ""
greeting = f"Hello, {name}" if name else "Hello, guest"
print(greeting) # Output: Hello, guest
# 非空字符串为真值
name = "Alice"
greeting = f"Hello, {name}" if name else "Hello, guest"
print(greeting) # Output: Hello, Alice
# 0 为假值,非 0 为真值
items = 0
message = "You have items" if items else "Your cart is empty"
print(message) # Output: Your cart is empty
items = 3
message = "You have items" if items else "Your cart is empty"
print(message) # Output: You have items嵌套求值
条件表达式中的值本身也可以是表达式,包括其他条件表达式。Python 会从内到外进行求值:
# value_if_true 本身就是一个计算
age = 25
price = age * 2 if age < 18 else age * 3
print(price) # Output: 75
# 步骤:age < 18 → False → 计算 age * 3 → 75
# 条件是一个复杂表达式
score = 85
grade = 90
status = "excellent" if score >= 80 and grade >= 85 else "good"
print(status) # Output: excellent
# 步骤:score >= 80 → True,grade >= 85 → True
# True and True → True → 返回 "excellent"10.4) 在赋值中使用条件表达式
条件表达式最常见的用途之一是在赋值中:我们希望根据条件,把变量设置为两个值之一。这种模式在真实代码中经常出现。
简单的赋值模式
我们来看一些实际示例,条件表达式如何让赋值更干净:
# 示例 1:根据会员身份设置折扣
is_member = True
discount = 0.15 if is_member else 0.05
print(f"Discount: {discount * 100}%") # Output: Discount: 15.0%
# 示例 2:确定运费
order_total = 45.00
shipping = 0 if order_total >= 50 else 5.99
print(f"Shipping: ${shipping:.2f}") # Output: Shipping: $5.99
# 示例 3:设置默认值
user_input = "" # 模拟空输入
page_size = int(user_input) if user_input else 10
print(f"Items per page: {page_size}") # Output: Items per page: 10与 if 语句对比
我们再看看同样的赋值用 if 语句怎么写,以体会差异:
# 使用 if 语句(更啰嗦)
is_member = True
if is_member:
discount = 0.15
else:
discount = 0.05
# 使用条件表达式(更紧凑)
is_member = True
discount = 0.15 if is_member else 0.05两种写法都能正确工作,但当你只是从两个值中选择一个时,条件表达式更简洁。if 语句版本需要四行,并且把变量名 discount 重复写了两次;而条件表达式用一行就能做同样的事。
使用一致逻辑进行多次赋值
当你需要基于同一个条件做多次赋值时,你有多种选择:
# 方法 1:多个条件表达式
is_premium = True
price = 99.99 if is_premium else 149.99
features = "all" if is_premium else "basic"
support = "priority" if is_premium else "standard"
# 方法 2:用一个 if 语句完成多次赋值
is_premium = True
if is_premium:
price = 99.99
features = "all"
support = "priority"
else:
price = 149.99
features = "basic"
support = "standard"在这种情况下,if 语句的方式(方法 2)通常更易读,因为它把相关的赋值放在一起,并且让它们之间的关系更清晰。条件表达式的方式(方法 1)也能工作,但它把条件重复了三次;如果条件需要修改,这会更难维护。
10.5) 在更大的表达式中使用条件表达式
因为条件表达式会产生值,所以它们可以嵌入到更大的表达式中。这能写出强大而紧凑的代码,不过需要注意保持可读性。
在算术运算中使用条件表达式
你可以把条件表达式作为算术运算的操作数:
# 条件加法
base_score = 80
bonus_eligible = True
final_score = base_score + (10 if bonus_eligible else 0)
print(f"Final score: {final_score}") # Output: Final score: 90在字符串格式化中使用条件表达式
条件表达式与 f-string 以及其他字符串操作能很好地配合:
# 示例 1:消息中的单复数处理
item_count = 1
message = f"You have {item_count} {'item' if item_count == 1 else 'items'}"
print(message) # Output: You have 1 item
item_count = 3
message = f"You have {item_count} {'item' if item_count == 1 else 'items'}"
print(message) # Output: You have 3 items
# 示例 2:根据时间的条件问候
hour = 14
greeting = f"Good {'morning' if hour < 12 else 'afternoon'}, user!"
print(greeting) # Output: Good afternoon, user!嵌套条件表达式
你可以嵌套条件表达式来处理多个条件,不过应当谨慎使用:
# 示例 1:三分分类
score = 85
grade = "A" if score >= 90 else ("B" if score >= 80 else "C")
print(f"Grade: {grade}") # Output: Grade: B
# 我们来跟踪一下:
# score >= 90?否(85 < 90)
# 所以计算 else 部分:("B" if score >= 80 else "C")
# score >= 80?是(85 >= 80)
# 返回 "B"
# 示例 2:温度分类
temp = 15
category = "hot" if temp > 25 else ("warm" if temp > 15 else "cold")
print(f"Category: {category}") # Output: Category: cold
# 示例 3:基于年龄的分级票价
age = 65
price = 0 if age < 5 else (8 if age < 18 else (12 if age < 65 else 8))
print(f"Ticket price: ${price}") # Output: Ticket price: $8关于嵌套的重要说明:虽然嵌套条件表达式是可行的,但它们很快会变得难以阅读。上面的第三个例子在技术上是正确的,但很难理解。我们会在 10.7 节讨论更好的替代方案。
在比较中使用条件表达式
你可以在比较运算中使用条件表达式:
# 示例 1:与条件值进行比较
base_value = 10
threshold = 15
is_large = True
result = base_value > (threshold if is_large else 5)
print(result) # Output: False
# 求值:base_value > 15 → 10 > 15 → False
# 示例 2:条件相等性检查
user_role = "admin"
required_role = "admin" if True else "user"
has_access = user_role == required_role
print(has_access) # Output: True10.6) 条件表达式 vs if 语句(表达式 vs 语句)
理解何时使用条件表达式、何时使用 if 语句,对于编写清晰且易维护的代码至关重要。区别归根结底在于 Python 中表达式与语句的根本差异。
表达式 vs 语句:核心差异
让我们更精确地澄清这些术语:
-
表达式(expression) 是由值、变量、运算符、函数调用等组成的组合,Python 会对其求值以产生一个值。示例:
2 + 3、"hello".upper()、x if x > 0 else 0 -
语句(statement) 是一条完整指令,用于执行某个动作。语句不会产生值——它们做事情。示例:
if x > 0: print("positive")、x = 5、for i in range(10): print(i)
# 这是一个表达式 —— 它会产生一个值(7)
result = 3 + 4
# 这是一个语句 —— 它会执行一个动作(打印)
print("Hello")
# 条件表达式是一种表达式
value = "yes" if True else "no" # 产生 "yes"
# if 语句是一种语句
if True:
value = "yes"
else:
value = "no"
# 执行赋值,但 if 本身不产生值何时使用条件表达式
条件表达式适用于以下场景:
1. 你在赋值时从两个值中选择一个:
# 条件表达式的良好用法
age = 16
status = "adult" if age >= 18 else "minor"
# 用 if 语句就不那么简洁
age = 16
if age >= 18:
status = "adult"
else:
status = "minor"2. 你需要在更大表达式中内联得到一个值:
# 良好用法 —— 在 f-string 中需要一个值
items = 1
print(f"You have {items} {'item' if items == 1 else 'items'}")
# Output: You have 1 item
# 用 if 语句会显得别扭 —— 需要先赋值
items = 1
if items == 1:
word = "item"
else:
word = "items"
print(f"You have {items} {word}")3. 逻辑简单,并且表达式仍然易读:
# 良好用法 —— 逻辑简单、清晰
discount = 0.15 if is_member else 0.05
max_value = a if a > b else b
sign = "positive" if x > 0 else "non-positive"何时使用 if 语句
在以下场景中使用 if 语句:
1. 每个分支需要执行多条语句:
# 使用 if 语句 —— 每个分支多个动作
if score >= 90:
grade = "A"
message = "Excellent work!"
bonus_points = 10
else:
grade = "B"
message = "Good job!"
bonus_points = 5
# 这里用条件表达式会很别扭:
# grade = "A" if score >= 90 else "B"
# message = "Excellent work!" if score >= 90 else "Good job!"
# bonus_points = 10 if score >= 90 else 5
# (不必要地重复条件)2. 你有超过两个分支(elif):
# 使用 if 语句 —— 多分支
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"
# 嵌套条件表达式会变得难以阅读:
# grade = "A" if score >= 90 else ("B" if score >= 80 else ("C" if score >= 70 else "F"))3. 某个分支应该什么都不做:
# 使用 if 语句 —— else 分支什么都不做
if error_occurred:
print("An error occurred")
log_error(error_message)
# 不需要 else
# 条件表达式要求两边都有分支:
# result = handle_error() if error_occurred else None # 别扭并排对比
我们来看看同一段逻辑用两种方式实现:
# 场景:设置运费
# 版本 1:条件表达式(适合简单的值选择)
order_total = 45.00
shipping = 0 if order_total >= 50 else 5.99
# 版本 2:if 语句(更啰嗦,但对一些人更清晰)
order_total = 45.00
if order_total >= 50:
shipping = 0
else:
shipping = 5.99
# 两者产生相同结果
print(f"Shipping: ${shipping:.2f}") # Output: Shipping: $5.99对于这个简单案例,条件表达式更简洁且同样清晰。但再看一个更复杂的场景:
# 场景:包含多个步骤的订单处理
# 版本 1:if 语句(适合多个动作)
order_total = 45.00
if order_total >= 50:
shipping = 0
discount = 0.10
message = "Free shipping applied!"
else:
shipping = 5.99
discount = 0
message = "Add $5 more for free shipping"
# 版本 2:条件表达式(别扭且重复)
order_total = 45.00
shipping = 0 if order_total >= 50 else 5.99
discount = 0.10 if order_total >= 50 else 0
message = "Free shipping applied!" if order_total >= 50 else "Add $5 more for free shipping"这里 if 语句版本更清晰,因为它把相关逻辑组织在一起,并且不重复条件。
10.7) 条件表达式何时提升可读性(以及何时不会)
条件表达式是一个强大的工具,但和任何工具一样,它也可能被误用。目标始终是写出不仅正确,而且清晰、可维护的代码。让我们探讨有效使用条件表达式的指导原则。
条件表达式何时提升可读性
1. 在两个值之间做简单、清晰的选择
当逻辑直观时,条件表达式表现最佳:
# 极佳用法 —— 一目了然
discount = 0.20 if is_member else 0.10
# 极佳用法 —— 含义明显
status = "active" if user_logged_in else "inactive"
# 极佳用法 —— 简单的布尔选择
can_vote = True if age >= 18 else False
# 不过这还能更简单:can_vote = age >= 182. 在表达式中进行内联取值
当你需要一个内联值,而把它拆出来会显得别扭时:
# 极佳用法 —— 自然的单复数处理
print(f"Found {count} {'result' if count == 1 else 'results'}")
# 极佳用法 —— 内联调整计算
total = base_price * (0.9 if is_sale else 1.0)
# 极佳用法 —— 条件格式化
output = f"Status: {status.upper() if is_error else status.lower()}"3. 设置默认值
条件表达式很适合提供兜底值:
# 极佳用法 —— 默认值模式
display_name = username if username else "Guest"
# 极佳用法 —— 带默认项的配置
page_size = user_preference if user_preference else 25
# 极佳用法 —— 安全除法
result = total / count if count > 0 else 0条件表达式何时损害可读性
1. 嵌套条件表达式
嵌套条件表达式会制造难以阅读的代码:
# 可读性差 —— 嵌套条件表达式
grade = "A" if score >= 90 else ("B" if score >= 80 else ("C" if score >= 70 else "F"))
# 更好 —— 使用 if-elif-else 语句
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"if-elif-else 版本一眼就能看懂。嵌套条件表达式则需要仔细解析才能理解逻辑。
2. 复杂条件
当条件本身很复杂时,条件表达式会变得难以阅读:
# 可读性差 —— 复杂条件
result = "eligible" if age >= 18 and income > 30000 and credit_score > 650 and not has_bankruptcy else "not eligible"
# 更好 —— 用 if 语句保持结构清晰
if age >= 18 and income > 30000 and credit_score > 650 and not has_bankruptcy:
result = "eligible"
else:
result = "not eligible"
# 更好 —— 拆分条件
meets_age_requirement = age >= 18
meets_income_requirement = income > 30000
meets_credit_requirement = credit_score > 650
has_clean_record = not has_bankruptcy
if meets_age_requirement and meets_income_requirement and meets_credit_requirement and has_clean_record:
result = "eligible"
else:
result = "not eligible"3. 在一行中组合多个条件表达式
在一行里组合多个条件表达式:
# 可读性差 —— 一行内容太多
price = base * (0.9 if is_member else 1.0) * (0.85 if is_sale else 1.0) + (0 if free_shipping else 5.99)
# 更好 —— 拆成步骤
member_multiplier = 0.9 if is_member else 1.0
sale_multiplier = 0.85 if is_sale else 1.0
shipping_cost = 0 if free_shipping else 5.99
price = base * member_multiplier * sale_multiplier + shipping_cost
# 或者在逻辑复杂时使用 if 语句
if is_member:
price = base * 0.9
else:
price = base
if is_sale:
price = price * 0.85
if free_shipping:
shipping_cost = 0
else:
shipping_cost = 5.99
price = price + shipping_cost最终结论
当条件表达式能让代码更清晰、更简洁时就使用它们。当你需要以下情况时使用 if 语句:
- 每个分支有多条语句
- 超过两个分支(
elif) - 复杂条件或复杂逻辑
- 需要副作用或动作,而不是选择一个值
拿不准时,优先选择清晰而不是炫技。代码被阅读的次数远多于被编写的次数,所以应当以读者为优化目标。
条件表达式是 Python 工具箱中很有价值的一项补充。它们让你在从两个值中选择一个时,能够写出简洁、优雅的代码。通过理解它们在何时提升可读性、何时不会,你就能做出更明智的选择。
需要记住的关键原则:
- 条件表达式会产生值,并且可以在任何需要值的地方使用
- 语法是
value_if_true if condition else value_if_false - Python 只会对相关分支求值(短路求值)
- 它们非常适合在赋值与表达式中做简单的值选择
- 当有多个动作、复杂逻辑或超过两个分支时使用
if语句 - 优先考虑可读性——如果条件表达式难以理解,就改用
if语句
随着你继续学习 Python,你会逐渐形成直觉,知道在何时使用条件表达式能让代码更好。先在简单场景中练习使用它们,渐渐你就能识别出它们最擅长发挥的模式。在下一章,我们将探索 while 循环(loop),它让我们能够基于条件重复执行动作——在本书这一部分已培养的决策能力之上继续构建。