2.5 控制流
你写的第一个脚本可能会包括一系列按顺序执行的语句,就像我们目前为止看到的所有例子一样。然而,编程的真正力量是根据不同的条件而改变的能力。类似于你可能会根据销售价格来决定在超市里买哪种蔬菜,你的代码应该基于数据类别,比如它是在处理点,还是线,来确定到底需要做什么。控制流是改变这种代码执行顺序的概念。
2.5.1 if语句
改变执行顺序最简单的方法是测试一个条件,并根据测试的结果做一些不同的事情。可以用一个if语句实现,下面是一个简单的例子:
if n == 1:
print('n equals 1')
else:
print('n does not equal 1')
如果n变量的值为1,则字符串“n equals 1”将被打印。否则,字符串“n does not equal 1”将被打印。要注意的是,if和else语句以冒号结尾,并且依赖if和else条件的代码会在该条件下缩进。这是一个要求,当你取消缩进代码时,代码随之退出所依赖的if或else条件。那么,下面的代码将打印什么?
n = 1
if n == 1:
print('n equals 1')
else:
print('n does not equal 1')
print('This is not part of the condition')
n等于1,所以相等的信息被打印出来,然后控制被转移到没有缩进的第1行代码,下面就是(输出)结果。
n equals 1
This is not part of the condition
也可以测试多个条件,例如:
if n == 1:
print('n equals 1')
elif n == 3:
print('n equals 3')
elif n > 5:
print('n is greater than 5')
else:
print('what is n?')
在这种情况下,n首先和1做比较。如果它不等于1,那么就和3做比较。如果它还是不等于3,然后检查n是否大于5。如果这些条件中没有一个是真的,执行else语句下的代码。只要想要,可以有多个elif语句,但只有一个if和else。类似于elif语句不是程序所必须的,else语句也不是必须的。如果喜欢,可以只用一个if语句。
这是一个很好的地方来阐述当测试条件时,不同的值可以判为真或假。记住,除非它们是空白的,否则字符串解析为真。下面用一个if语句来测试:
>>> if '':
... print('a blank string acts like True')
... else:
... print('a blank string acts like false')
...
a blank string acts like false
如果使用了一个包含任何字符的字符串,即使是一个空格,前面的例子也会解析为真,而不是假。如果你打开Python控制台,去试试看吧。下面再看一个解析为真的例子,因为列表不为空:
>>> if [1]:
... print('a non-empty list acts like True')
... else:
... print('a non-empty list acts like False')
...
a non-empty list acts like True
可以使用相同的想法来测试一个数字不等于零,因为零是False,但任何其他数字,正或负,都将被视为True。
2.5.2 while语句
一个while语句会执行一个代码块,只要条件为真。如果条件判为真,那么代码就被执行。然后再次检查条件,如果它仍然为真,代码将再次执行,直到条件判为假。如果条件一直为真,代码会永远执行下去,称为死循环,这是要极力避免的。下面是while循环的例子:
>>> n = 0
>>> while n < 5:
... print(n)
... n += 1
...
0
1
2
3
4
“+=”意味着累加,所以(每执行一次)n递增1。当n等于5时,不再小于5,因此这个条件变为假,然后代码不再执行。
2.5.3 for语句
一个for语句可以遍历一个序列,并为每个值做事。当写一个for语句时,不仅提供序列的遍历,也要提供一个变量名。每执行一次循环,该变量包含序列中一个不同的值。下面这个例子遍历了一个名单,并为每个人打印一条消息。
>>> names = ['Chris', 'Janet', 'Tami']
>>> for name in names:
... print('Hello {}!'.format(name))
...
Hello Chris!
Hello Janet!
Hello Tami!
第1次执行循环时,名称变量等于“Chris”,第2次是“Janet”,最后一次是“Tami”。我称这个变量为name,但它可以是任何你想叫的名字。
range函数
range函数可以很容易地遍历一个序列。虽然这个函数有更多的参数,使用它最简单的方法是提供一个数字n,并且它将创建从0到n-1的序列。例如,下面这个例子将计算循环执行的次数:
>>> n = 0
>>> for i in range(20):
... n += 1
...
>>> print(n)
20
这个代码中没有使用变量i,但没有什么阻止你使用它。让我们用它来计算20的阶乘,这次我们提供一个起始值为1的序列,并让它增长到21,但不包括21本身。
>>> n = 1
>>> for i in range(1, 21):
... n = n * i
...
>>> print(n)
2432902008176640000
在后面的章节中,你将看到这个变量对于访问数据集中不能直接迭代的单个元素时也很有用。
2.5.4 break、continue和else
一些语句适用于while和for循环。第1个是break,它将执行完全跳出循环的操作,正如在这个例子中,i等于3时停止循环:
>>> for i in range(5):
... if i == 3:
... break
... print(i)
...
0
1
2
如果没有break语句,这个循环将从0打印到4。
continue语句会跳过在当前循环迭代过程中通常会执行的其余部分代码,跳转到循环的顶部,并开始下一次迭代。在这个示例中,如果i等于3,contine语句用于跳过打印i这行代码。
>>> for i in range(5):
... if i == 3:
... continue
... print(i)
...
0
1
2
4
循环也可以有else语句。该分句的代码在循环执行时被执行,除非被break语句中断。这里,我们将检查2是否在一个数字列表中。如果是,会跳出循环。否则,else语句用来通知我们数字没有找到。在第一种情况中,数字找到,break语句用于退出循环,else语句将被忽略。
>>> for i in [0, 5, 7, 2, 3]:
... if i == 2:
... print('Found it!')
... break
... else:
... print('Could not find 2')
...
Found it!
但如果数字找不到,就不调用break语句,而是执行else分句。
>>> for i in [0, 5, 7, 3]:
... if i == 2:
... print('Found it!')
... break
... else:
... print('Could not find 2')
...
Could not find 2
如果在一个列表中没有找到适当的值,可以使用这个模式来设置一个默认值。例如,你需要找到并编辑文件夹中一个特定格式的文件,如果你找不到正确的文件格式,需要创建一个。可以通过遍历文件夹中的文件,如果找到一个合适的文件,可以跳出循环。可以在else分句中创建一个新文件,只有在没有找到合适的现有文件时,代码才会执行。