核心:控制流 ============== 截止到现在,在我们所看过的程序中,总是有一系列语句从上到下精确排列,并交由Python忠实地执行。 如果你想改变这一工作流程,需要程序作出一些决定,依据不同的情况去完成不同的事情,应该怎么做? 例如依据每天时间的不同打印出‘早上好’ 或 ‘晚上好’ ? 你可能已经猜到了,这是通过控制流语句来实现的。在 Python 中有三种控制流语句——\ ``if`` ``for`` 和 ``while``\ 。 所有控制流语句分为判断部分和非判断部分,比如: .. code:: python number = 23 guess = int(input('Enter an integer : ')) if guess == number: # 新块从这里开始 print('Congratulations, you guessed it.') print('(but you do not win any prizes!)') # 新块在这里结束 elif guess < number: # 另一代码块 print('No, it is a little higher than that') # 你可以在此做任何你希望在该代码块内进行的事情 else: print('No, it is a little lower than that') # 你必须通过猜测一个大于(>)设置数的数字来到达这里。 这里有if,elif,else,或者for的语句是判断部分,判断分支的方向,或者循环是否应该结束。 判断部分结尾一定要用冒号结尾,而且需要使用英文标点。。否则会出现错误: ``SyntaxError: invalid syntax`` 非判断部分,同一层分支(或循环)需要使用相同个数的 ``tab`` 制表符或者四个空格来区分。不要混用tab或者空格,否则会出现错误: `` IndentationError: unexpected indent`` ``if`` 语句 ----------- ``if`` 语句用以检查条件:\ *如果* 条件为真(True),我们将运行一块语句(称作 *if-block* 或 *if 块*\ ),\ *否则* 我们将运行另一块语句(称作 *else-block* 或 *else 块*\ )。其中 *else* 从句是可选的。 案例(保存为 ``if.py``\ ): .. code:: python number = 23 guess = int(input('Enter an integer : ')) if guess == number: # 新块从这里开始 print('Congratulations, you guessed it.') print('(but you do not win any prizes!)') # 新块在这里结束 elif guess < number: # 另一代码块 print('No, it is a little higher than that') # 你可以在此做任何你希望在该代码块内进行的事情 else: print('No, it is a little lower than that') # 你必须通过猜测一个大于(>)设置数的数字来到达这里。 print('Done') # 这最后一句语句将在 # if 语句执行完毕后执行。 输出: .. code:: console $ python if.py Enter an integer : 50 No, it is a little lower than that Done $ python if.py Enter an integer : 22 No, it is a little higher than that Done $ python if.py Enter an integer : 23 Congratulations, you guessed it. (but you do not win any prizes!) Done **它是如何工作的** 在这个程序中,我们根据用户猜测的数字来检查这一数字是否是我们所设置的。我们将变量 ``number`` 设为任何我们所希望的整数,例如 ``23``\ 。然后,我们通过 ``input()`` 函数来获取用户的猜测数。所谓函数是一种可重复使用的程序。我们将在\ :doc:`下一章 <./functions>`\ 详细讨论它。 我们为内置的 ``input`` 函数提供一串打印到屏幕上的字符串并等待用户的输入。一旦我们输入了某些内容并按下键盘上的 ``enter`` 键,\ ``input()`` 函数将以字符串的形式返回我们所输入的内容。然后我们通过 ``int`` 将这个字符串转换成一个整数并将其储存在变量 ``guess`` 中。实际上,\ ``int`` 是一个类(Class),但你现在你所需要知道的就是你可以使用它将一串字符串转换成一个整数(假设这个字符串的文本中含有一个有效的整数)。 接下来,我们将用户提供的猜测数与我们所选择的数字进行对比。如果它们相等,我们就打印一条成功信息。在这里要注意到我们使用缩进级别来告诉 Python 哪些语句分别属于哪个块。这便是为什么在 Python 中缩进如此重要。我希望你能够坚持“缩进一致”的原则。 另外需要注意的是 ``if`` 语句在结尾处包含一个冒号——我们以此告知 Python 后面会有一个语句块。 然后,我们检查猜测数是否小于我们选择的数字,如果是,我们将告诉用户他们必须猜一个更高一些的数字。在这里我们使用的是 ``elif`` 语句,它们实际上将两个相连的 ``if else-if else`` 语句合并成一句 ``if-elif-else`` 语句。这能够使程序更加简便,并且可以减少所需要的缩进量。 ``elif`` 和 ``else`` 同样都必须有一个冒号在其逻辑行的末尾,后面跟着与它们相应的语句块(当然,别忘了恰当的缩进)。 你可以在 if 块的 一个 ``if`` 语句中设置另一个 ``if`` 语句,并可以如此进行下去——这被称作嵌套的 ``if`` 语句。 要记住 ``elif`` 和 ``else`` 部分都是可选的。一个最小规模且有效的 ``if`` 语句是这样的: .. code:: python if True: print('Yes, it is true') 当 Python 完整执行了 ``if`` 语句及与其相关的 ``elif`` 和 ``else`` 子句后,它将会移动至包含 ``if`` 语句的代码块的下一句语句中。在本例中,也就是主代码块(程序开始执行的地方),其下一句语句就是 ``print('Done')`` 语句。在完成这些工作后,Python 会发现已行至程序末尾并宣告工作的完成。 尽管这是一个非常简单的程序,我也一直在其中指出你应该注意的事情。所有的这些都可算是简单易懂(对于那些具有 C/C++ 背景的人来说是相当简单易懂)。不过在开始时它们还是可能会不断吸引你的注意,不断地去在意它们。但经过一些更丰富的操作后你就会习惯它们及其中的逻辑,它们对于你来说将会成为“自然而然”的事情。 **针对 C/C++ 程序员的提示** Python 中不存在 ``switch`` 语句。你可以通过使用 ``if..elif..else`` 语句来实现同样的事情(在某些情况下,使用一部\ :doc:`字典 <./data_structures>` \ 能够更快速地完成)。 ``while`` 语句 -------------- ``while`` 语句能够让你在条件为真的前提下重复执行某块语句。 ``while`` 语句是 *循环(Looping)* 语句的一种。\ ``while`` 语句同样可以拥有 ``else`` 子句作为可选选项。 案例(保存为 ``while.py``\ ): .. code:: python number = 23 running = True while running: guess = int(input('Enter an integer : ')) if guess == number: print('Congratulations, you guessed it.') # 这将导致 while 循环中止 running = False elif guess < number: print('No, it is a little higher than that.') else: print('No, it is a little lower than that.') else: print('The while loop is over.') # 在这里你可以做你想做的任何事 print('Done') 输出: .. code:: console $ python while.py Enter an integer : 50 No, it is a little lower than that. Enter an integer : 22 No, it is a little higher than that. Enter an integer : 23 Congratulations, you guessed it. The while loop is over. Done **它是如何工作的** 在这一程序中,我们依旧通过猜数游戏来演示,不过新程序的优点在于能够允许用户持续猜测直至他猜中为止——而无需像我们在上一节中所做的那样,每次猜测都要重新运行程序。这种变化恰到好处地演示了 ``while`` 语句的作用。 首先我们将 ``input`` 与 ``if`` 语句移到 ``while`` 循环之中,并在 while 循环开始前将变量 ``running`` 设置为 ``True``\ 。程序开始时,我们首先检查变量 ``running`` 是否为 ``True``\ ,之后再执行相应的 *while 块*\ 。在这一代码块被执行之后,将会重新对条件进行检查,在本例中也就是 ``running`` 变量。如果它依旧为 ``True``\ ,我们将再次执行 while 块,否则我们将继续执行可选的 else 块,然后进入到下一个语句中。 ``else`` 代码块在 ``while`` 循环的条件变为 ``False`` 时开始执行——这个开始的时机甚至可能是在第一次检查条件的时候。如果 ``while`` 循环中存在一个 ``else`` 代码块,它将总是被执行,除非你通过 ``break`` 语句来中断这一循环。 ``True`` 和 ``False`` 被称作布尔(Boolean)型,你可以将它们分别等价地视为 ``1`` 与 ``0``\ 。 **针对 C/C++ 程序员的提示** 你可以在 ``while`` 循环中使用 ``else`` 从句。 ``for`` 循环 ------------ ``for...in`` 语句是另一种循环语句,其特点是会在一系列对象上进行_迭代(Iterates)_,意即它会遍历序列中的每一个项目。 我们将在后面的\ :doc:`序列(Sequences) <./data_structures>`\ 章节中了解有关它的更多内容。现在你所需要的就是所谓队列就是一系列项目的有序集合。 案例(保存为 ``for.py`` \ ): .. code:: python for i in range(1, 5): print(i) else: print('The for loop is over') 输出: .. code:: console $ python for.py 1 2 3 4 The for loop is over **它是如何工作的** 在这一程序中,我们打印了一个数字序列。我们通过内置的 ``range`` 函数生成这一数字序列。 在这里我们所要做的事情是提供两个数字,而 ``range`` 将会返回一个数字序列,从第一个数字开始,至第二个数字结束。举个例子,\ ``range(1,5)`` 将输出序列 ``[1, 2, 3, 4]`` \ 。在默认情况下,\ ``range`` 将会以 1 逐步递增。如果我们向 ``range`` 提供第三个数字,则这个数字将成为逐步递增的加数。同样举个例子来说明,\ ``range(1,5,2)`` 将会输出 ``[1, 3]``\ 。要记住这一序列扩展 *直到* 第二个数字,也就是说,它 *不会* 包括第二个数字在内。 另外需要注意的是,\ ``range()`` 在python3中是一个数字序列对象,如果你希望获得完整的数字列表,要在使用 ``range()`` 时调用 ``list()``\ 。例如下面这样:\ ``list(range(5))`` ,它将会返回 ``[0, 1, 2, 3, 4]``\ 。有关列表的详细解释将会在 \ :doc:`《数据结构》一章 <./data_structures>` \ 呈现。 然后 ``for`` 循环就会在这一范围内展开递归——\ ``for i in range(1,5)`` 等价于 ``for i in [1, 2, 3, 4]``\ ,这个操作将依次将队列里的每个数字(或是对象)分配给 ``i``\ ,一次一个,然后以每个 ``i`` 的值执行语句块。在本例中,我们这一语句块所做的就是打印出这些值。 同样要记住,\ ``else`` 部分是可选的。当循环中包含他时,它总会在 ``for`` 循环结束后开始执行,除非程序遇到了 `break <06.control.md#break-statement>`__ 语句。 另一个需要注意的地方是 ``for...in`` 能在任何队列中工作。在这里,我们有的是通过内置的 ``range`` 函数生成的一串数字列表,但总体来说我们可以包含任何类型对象的队列!我们将会在后面的章节详细解释这一观念。 **针对 C/C++/Java/C# 程序员的提示** Python 中的 ``for`` 循环和 C/C++ 中的 ``for`` 循环可以说是完全不同。C# 程序员会注意到 Python 中的 ``for`` 循环与 C# 中的 ``foreach`` 循环相似。Java 程序员则会注意到它同样与 Java 1.5 中的 ``for (int i : IntArray)`` 无甚区别。 在 C/C++ 中,如果你希望编写 ``for (int i = 0; i < 5; i++)``\ ,那么在 Python 你只需要写下 ``for i in range(0,5)``\ 。正如你所看到的,Python 中的 ``for`` 循环将更加简单,更具表现力且更不容易出错。 .. _break-statement: ``break`` 语句 -------------- ``break`` 语句用以 *中断* (Break)循环语句,也就是中止循环语句的执行,即使循环条件没有变更为 ``False``\ ,或队列中的项目尚未完全迭代依旧如此。 有一点需要尤其注意,如果你 *中断* 了一个 ``for`` 或 ``while`` 循环,任何相应循环中的 ``else`` 块都将_不会_被执行。 案例(保存为 ``break.py``\ ): .. code:: python while True: s = input('Enter something : ') if s == 'quit': break print('Length of the string is', len(s)) print('Done') 输出: .. code:: console $ python break.py Enter something : Programming is fun Length of the string is 18 Enter something : When the work is done Length of the string is 21 Enter something : if you wanna make your work also fun: Length of the string is 37 Enter something : use Python! Length of the string is 11 Enter something : quit Done **它是如何工作的** 在本程序中,我们重复地接受用户的输入内容并打印出每一次输入内容的长度。我们通过检查用户输入的是否是 ``quit`` 这一特殊条件来判断是否应该终止程序。我们通过_中断_循环并转进至程序末尾来结束这一程序。 输入字符串的长度可以通过内置的 ``len`` 函数来找到。 记住,\ ``break`` 语句同样可以适用于 ``for`` 循环。 .. _continue-statement: ``continue`` 语句 ----------------- ``continue`` 语句用以告诉 Python 跳过当前循环块中的剩余语句,并_继续_该循环的下一次迭代。 案例(保存为 ``continue.py``\ ): .. code:: python while True: s = input('Enter something : ') if s == 'quit': break if len(s) < 3: print('Too small') continue print('Input is of sufficient length') # 自此处起继续进行其它任何处理 输出: .. code:: console $ python continue.py Enter something : a Too small Enter something : 12 Too small Enter something : abc Input is of sufficient length Enter something : quit **它是如何工作的** 在本程序中,我们接受来自用户的输入内容,但是只有在输入的字符串其长至少 3 字符我们才会对其进行处理。为此,我们使用内置的 ``len`` 函数和来获取字符串的长度,如果其长度小于 3,我们便通过使用 ``continue`` 语句跳过代码块中的其余语句。否则,循环中的剩余语句将被执行,并在此处进行我们所希望的任何类型的处理。 要注意 ``continue`` 语句同样能用于 ``for`` 循环。 练习 ----------------- 1.如果数a能被数b整除,a就叫做b的倍数,b就叫做a的约数。 如:6 的约数为 2 和 3 。 几个整数中公有的约数,叫做这几个数的公约数;其中最大的一个,叫做这几个数的最大公约数。 如: 30 和 18 的最大公约数为 6 。 求 8191 和 9689 的最大公约数 2.求以下方程的数值解: 代数方程(包含加、减、乘、除、乘方、开方六则运算的方程): x \ :sup:`5` = 3x 超越方程(包含指数、对数、三角函数等超越函数): 2 \ :sup:`x` = 3x |image0| 总结 ---- 我们已经了解了三种控制流语句——\ ``if``\ ,\ ``while`` 和 ``for`` ——及其相关的 ``break`` 与 ``continue`` 语句是如何工作的。这些语句是 Python 中一些最常用的部分,因此,习惯去使用它们是必要的。 .. |image0| image:: ../pic/2_structure.png