2.11. 条件语句¶
条件语句(conditional)只在某个测试求值为真时才运行一段代码。关键字是 if,后面可选地跟一个或多个 elif("else if")分支以及最后的 else。
n = 42
if n > 0:
print("positive")
elif n < 0:
print("negative")
else:
print("zero")
每个分支的主体是在它下面缩进的所有内容(按惯例为四个空格)。Python 按顺序检查各分支,运行测试为真的第一个分支,并跳过其余分支。else 块仅在前面每个测试都为假时才运行;它始终是可选的。
始终只有一个分支会运行。测试从上到下依次求值,直到有一个成功为止;其余的都被跳过。¶
2.11.1. 真值性¶
if 中的测试不必返回 True 或 False——任何值都被视为真值(truthy)或假值(falsy)。假值有:
其他一切都是真值。这让你能写出紧凑的测试:
if name: # false on empty string
print("hello", name)
if items: # false on empty list, dict, etc.
process(items)
请注意真值性会改变含义。if value: 与 if value is not None: 并不相同——当 value 为 0 或 "" 时前者也为假。当你真正想表达"这是否恰好是 None"时,请显式使用 is None / is not None。
2.11.2. 三元表达式¶
条件语句可以出现在表达式内部:
label = "even" if n % 2 == 0 else "odd"
读作"如果 n % 2 == 0 则 label 为 "even",否则为 "odd""。它适合写单行代码;对于超过一行的任何内容,完整的 if 语句更易读。
2.11.3. 嵌套与提前返回¶
条件语句可以任意深地嵌套,但每多一层缩进都会让函数更难读。下面的例子在做真正的工作之前检查了四个条件,并把有用的那一行埋在了四层缩进之内:
def process(item):
if item is not None:
if item.is_valid():
if item.size() > 0:
if item.owner == "me":
return do_the_work(item)
return None
有两种模式能把这类代码扁平化。
2.11.3.1. 用提前返回作为守卫¶
先处理每个"提前退出"的情况,每个都带有自己的 return,这样主逻辑就保持在外层缩进。每个守卫读作"这不是我们要处理的情况;离开":
def process(item):
if item is None:
return None
if not item.is_valid():
return None
if item.size() == 0:
return None
if item.owner != "me":
return None
return do_the_work(item)
现在"主路径"是函数底部的一行,而不是埋在四层之内。这种风格有时被称为守卫子句(guard clause)模式。
2.11.3.2. 用 and / or 组合多个测试¶
当同一个分支需要多个条件同时成立时,用 and 来组合它们,而不是嵌套。各自能独立触发该分支的条件则用 or 组合:
# all must hold -- use `and`
if user.is_admin() and user.has_permission("write") and not locked:
save()
# any one of them is enough -- use `or`
if c == " " or c == "\t" or c == "\n":
whitespace_count += 1
两种形式都会短路求值,因此右侧代价高昂的检查只在左侧较廉价的检查尚未确定结论时才会运行。