程序就是一系列指令。但编程真正的力量不仅在于运行(或“执行”)一条接一条的指令,就像周末的任务清单那样。根据表达式求值的结果,程序可以决定跳过指令,重复指令,或从几条指令中选择一条运行。实际上,你几乎永远不希望程序从第一行代码开始,简单地执行每行代码,直到最后一行。“控制流语句”可以决定在什么条件下执行哪些python语句。
图1展示了一张流程图,内容是如果下雨怎么办。按照箭头构成的路径,从开始到结束。
在流程图中,通常有不止一种方法从开始走到结束。计算机程序中的代码行也是这样。流程图用菱形表示这些分支节点,其他步骤用矩形表示。开始和结束步骤用带圆角的矩形表示。
但在学习流程控制语句之前,首先要学习如何表示这些yes和no选项。同时你也需要理解,如何将这些分支节点写成Python代码。要做到这一点,让我们先看看布尔值、比较操作符和布尔操作符。

图1 一张流程图,告诉你如果下雨要做什么
1 布尔值虽然整型、浮点型和字符串数据类型有无数种可能的值,但“布尔”数据类型只有两种值:True和False。Boolean(布尔)的首字母大写,因为这个数据类型是根据数学家George Boole命名的。在作为Python代码输入时,布尔值True和False不像字符串,两边没有引号,它们总是以大写字母T或F开头,后面的字母小写。在交互式环境中输入下面内容,其中有些指令是故意弄错的,它们将导致出错信息。
>>> spam = True >>> spam True >>> true Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> true NameError: name 'true' is not defined >>> True = 2 + 2 SyntaxError: assignment to keyword像其他值一样,布尔值也用在表达式中,并且可以保存在变量中。如果大小写不正确,或者试图使用True和False作为变量名,Python就会给出错误信息。
2 比较操作符“比较操作符”比较两个值,求值为一个布尔值。表1列出了比较操作符。
表1 比较操作符操作符
操作符 含义 == 等于 != 不等于 < 小于 > 大于 <= 小于等于 >= 大于等于这些操作符根据给它们提供的值,求值为True或False。现在让我们尝试一些操作符,从==和!=开始。
>>> 42 == 42 True >>> 42 == 99 False >>> 2 != 3 True >>> 2 != 2 False如果两边的值一样,==(等于)求值为True。如果两边的值不同,!=(不等于)求值为True。==和!=操作符实际上可以用于所有数据类型的值。
>>> 'hello' == 'hello' True >>> 'hello' == 'Hello' False >>> 'dog' != 'cat' True >>> True == True True >>> True != False True >>> 42 == 42.0 True >>> 42 == '42' False请注意,整型或浮点型的值永远不会与字符串相等。表达式42 == '42'求值为False是因为,Python认为整数42与字符串'42'不同。
另一方面,<、>、<=和>=操作符仅用于整型和浮点型值。
>>> 42 < 100 True >>> 42 > 100 False >>> 42 < 42 False >>> eggCount = 42 >>> eggCount <= 42 True >>> myAge = 29 >>> myAge >= 10 True操作符的区别
你可能已经注意到,==操作符(等于)有两个等号,而=操作符(赋值)只有一个等号。这两个操作符很容易混淆。只要记住:
==操作符(等于)问两个值是否彼此相同。 =操作符(赋值)将右边的值放到左边的变量中。为了记住谁是谁,请注意==操作符(等于)包含两个字符,就像!=操作符(不等于)包含两个字符一样。
你会经常用比较操作符比较一个变量和另外某个值。就像在例子eggCount <= 42和myAge >= 10中一样(毕竟,除了在代码中输入'dog' != 'cat'以外,你本来也可以直接输入True)。稍后,在学习控制流语句时,你会看到更多的例子。
3. 布尔操作符3个布尔操作符(and、or和not)用于比较布尔值。像比较操作符一样,它们将这些表达式求值为一个布尔值。让我们仔细看看这些操作符,从and操作符开始。
(1) 二元布尔操作符and和or操作符总是接受两个布尔值(或表达式),所以它们被认为是“二元”操作符。如果两个布尔值都为True,and操作符就将表达式求值为True,否则求值为False。在交互式环境中输入某个使用and的表达式,看看效果。
>>> True and True True >>> True and False False“真值表”显示了布尔操作符的所有可能结果。表2是操作符and的真值表。
表2 and操作符的真值表 表达式 求值为 True and True TRUE True and False FALSE False and True FALSE False and False FALSE另一方面,只要有一个布尔值为真,or操作符就将表达式求值为True。如果都是False,所求值为False。
>>> False or True True >>> False or False False可以在or操作符的真值表中看到每一种可能的结果,如表3所示。
表3 or操作符的真值表 表达式 求值为 True or True TRUE True or False TRUE False or True TRUE False or False FALSE (2) not操作符和and和or不同,not操作符只作用于一个布尔值(或表达式)。not操作符求值为相反的布尔值。
>>> not True False >>> not not not not True True就像在说话和写作中使用双重否定,你可以嵌套not操作符,虽然在真正的程序中并不经常这样做。表4展示了not的真值表。
表4 not操作符的真值表 表达式 求值为 not True FALSE not False TRUE 4 混合布尔和比较操作符既然比较操作符求值为布尔值,就可以和布尔操作符一起,在表达式中使用。
回忆一下,and、or和not操作符称为布尔操作符是因为,它们总是操作于布尔值。虽然像4 < 5这样的表达式不是布尔值,但可以求值为布尔值。在交互式环境中,尝试输入一些使用比较操作符的布尔表达式。
>>> (4 < 5) and (5 < 6) True >>> (4 < 5) and (9 < 6) False >>> (1 == 2) or (2 == 2) True计算机将先求值左边的表达式,然后再求值右边的表达式。知道两个布尔值后,它又将整个表达式再求值为一个布尔值。你可以认为计算机求值(4 < 5)和(5 < 6)的过程,如图2所示。

图2 (4 < 5)和 (5 < 6) 求值为True的过程
也可以在一个表达式中使用多个布尔操作符,与比较操作符一起使用。
>>> 2 + 2 == 4 and not 2 + 2 == 5 and 2 * 2 == 2 + 2 True和算术操作符一样,布尔操作符也有操作顺序。在所有算术和比较操作符求值后,Python先求值not操作符,然后是and操作符,然后是or操作符。
5 控制流的元素控制流语句的开始部分通常是“条件”,接下来是一个代码块,称为“子句”。在开始学习具体的Python控制流语句之前,我将介绍条件和代码块。
(1) 条件你前面看到的布尔表达式可以看成是条件,它和表达式是一回事。“条件”只是在控制流语句的上下文中更具体的名称。条件总是求值为一个布尔值,True或False。控制流语句根据条件是True还是False,来决定做什么。几乎所有的控制流语句都使用条件。
(2)代码块一些代码行可以作为一组,放在“代码块”中。可以根据代码行的缩进,知道代码块的开始和结束。代码块有3条规则。
1.缩进增加时,代码块开始。
2.代码块可以包含其他代码块。
3.缩进减少为零,或减少为外面包围代码块的缩进,代码块就结束了。
看一些有缩进的代码,更容易理解代码块。所以让我们在一小段游戏程序中,寻找代码块,如下所示:
if name == 'Mary': print('Hello Mary') if password == 'swordfish': print('Access granted.') else: print('Wrong password.')第一个代码块开始于代码行print('Hello Mary'),并且包含后面所有的行。在这个代码块中有另一个代码块,它只有一行代码:print('Access Granted.')。第三个代码块也只有一行:print('Wrong password.')。
6 程序执行“程序执行”(或简称“执行”)这一术语是指当前被执行的指令。如果将源代码打印在纸上,在它执行时用手指指着每一行代码,你可以认为手指就是程序执行。
但是,并非所有的程序都是从上至下简单地执行。如果用手指追踪一个带有控制流语句的程序,可能会发现手指会根据条件跳过源代码,有可能跳过整个子句。
7 控制流语句现在,让我们来看最重要的控制流部分:语句本身。语句代表了在图1的流程图中看到的菱形,它们是程序将做出的实际决定。
(1) if语句最常见的控制流语句是if语句。if语句的子句(也就是紧跟if语句的语句块),将在语句的条件为True时执行。如果条件为False,子句将跳过。
在英文中,if语句念起来可能是:“如果条件为真,执行子句中的代码。”在Python中,if语句包含以下部分:
if关键字; 条件(即求值为True或False的表达式); 冒号; 在下一行开始,缩进的代码块(称为if子句)。例如,假定有一些代码,检查某人的名字是否为Alice(假设此前曾为name赋值)。
if name == 'Alice': print('Hi, Alice.')所有控制流语句都以冒号结尾,后面跟着一个新的代码块(子句)。语句的if子句是代码块,包含print('Hi, Alice.')。图3展示了这段代码的流程图。

图3 if语句的流程图
(2) else语句if子句后面有时候也可以跟着else语句。只有if语句的条件为False时,else子句才会执行。在英语中,else语句读起来可能是:“如果条件为真,执行这段代码。否则,执行那段代码”。else语句不包含条件,在代码中,else语句中包含下面部分:
else关键字; 冒号; 在下一行开始,缩进的代码块(称为else子句)。回到Alice的例子,我们来看看使用else语句的一些代码,在名字不是Alice时,提供不一样的问候。
if name == 'Alice': print('Hi, Alice.') else: print('Hello, stranger.')图4 展示了这段代码的流程图。

图4 else语句的流程图
(3) elif语句虽然只有if或else子句会被执行,但有时候可能你希望,“许多”可能的子句中有一个被执行。elif语句是“否则如果”,总是跟在if或另一条elif语句后面。它提供了另一个条件,仅在前面的条件为False时才检查该条件。在代码中,elif语句总是包含以下部分:
elif关键字; 条件(即求值为True或False的表达式); 冒号; 在下一行开始,缩进的代码块(称为elif子句)。让我们在名字检查程序中添加elif,看看这个语句的效果。
if name == 'Alice': print('Hi, Alice.') elif age < 12: print('You are not Alice, kiddo.')这一次,检查此人的年龄。如果比 12 岁小,就告诉他一些不同的东西。可以在图5中看到这段代码的流程图。
如果age < 12为True并且name == 'Alice'为Fa