本文主要介绍 Python 的流程控制,包括 if、while、for 的用法以及一些注意事项等。阅读本文预计需要 8 min。


Python入门之Python流程控制

  • 1. 前言
  • 2. 条件控制语句 if
  • 3. 循环控制语句 while
  • 4. 循环控制语句 for
  • 5. 巨人的肩膀


1. 前言

计算机是按照一定的顺序执行代码,从而实现各种各样的功能。编程就是将你的所思所想转化为一行行代码,然后交给计算机来帮你执行。而要保证代码按照你预想的顺序执行,就需要你掌握代码执行的流程。这也是我们看懂别人代码的基础。

溪流从源头顺流而下,有时可能会有分支,有时可能会有漩涡,最后汇入大海。程序也如溪流一样,有一个程序入口,正常就按顺序执行,有时会有分支结构,有时会有循环结构,最后有一个程序出口,程序结束。程序和现实往往惊人的相似,这是因为程序就是对现实不断的抽象,越来越接近我们现实,来帮助我们解决现实中的遇到的问题。

在 Python 中流程控制主要有顺序执行、选择执行、循环执行。顺序执行指按照代码的顺序一行一行依次执行。选择执行指一段代码条件成立执行,否则不执行。循环执行指一段代码多次执行。顺序执行比较简单,就不多说了。Python 中选择执行主要是通过 if 条件语句控制的。另外 Python 中 try 异常错误处理语句也是一种选择执行语句,只不过一般我们是用它处理错误异常的,这部分我们先不讲解。Python 中循环语句主要是通过 while 语句 和 for 语句实现的。接下来我们将详细介绍 if while for 语句的用法。主要内容:

  • if
  • if…else
  • if…elif…else
  • while
  • wile…else
  • for
  • for…else

2. 条件控制语句 if

if 语句是把我们现实中处理一件事物的所有可能性都列出来,并进行相应的处理。Python 中 if 语句的语法如下:

if expression:
    代码块1
(elif expression:
    代码块2
...)
[else:
    代码块3]

说明:expression 是条件表达式。代码块是英文 suite 翻译而来,可以是一行或多行代码,只要保证是相同的缩进。() 括起来的部分表示可以出现 0 次或者多次,常用于超过 2 个可能时。[] 部分代表可选,可以写,也可以不写。

程序会依次去判断每一个 expression ,一旦 expression 为真,就执行相应的 suite,然后跳过后面所有的 expression 判断和 suite 的执行,如果所有的 expression 都不为真的话,就会执行 else 语句的 suite

注意 if 可以单独使用,但是elifelse 都不能单独使用,需要和 if 配对使用。

if 用法测试如下:

print('用法一:只使用 if')
if 2 > 1:
    print('2 > 1')

print('用法二:使用 if...else 处理两种可能,即单分支')
score = 66
if score > 60:
    print('恭喜你!合格啦!')
else:
    print('很遗憾,您未能通过本次考试...')

print('用法三:使用if...elif...elif...else 处理多种可能,即多分支')
math_score = 100
if math_score >= 90:
    print('天才!^_^')
elif math_score >= 80 and math_score < 90:
    print('优秀')
elif math_score >= 60 and math_score < 80:
    print('良好')
else:
    print('不及格...T_T')

结果输出:
用法一:只使用 if
2 > 1
用法二:使用 if...else 处理两种可能,即单分支
恭喜你!合格啦!
用法三:使用if...elif...elif...else 处理多种可能,即多分支
天才!^_^

如果我们暂时不知道怎么处理一种情况,或者想直接忽略这种情况,那么我们可以用 pass 语句来替换 suitepass 语句是一个占位符,表示什么也不做,以后你想到要怎么操作,就用相应的代码替换掉 pass 语句即可。

Python 中如果空列表出现在 expression,会被认为是假,而不执行相应的 suite。如

if []:
    print('Python')

print('Python') 不会被执行,因为 [] 为假。

Python 中会被认为是假的情况有:

  1. 被定义为 None 或者 False 的常量。
  2. 表示 0 的数值:0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  3. 序列或者集合为空时:’’, (), [], {}, set(), range(0)

这里需要注意一点,当我们用 andor 运算时,我们得到的结果是其中一个操作数,而不是 0 或 1。测试如下:

In [5]: 2 or 3
Out[5]: 2

In [6]: 0 or 3
Out[6]: 3

In [7]: 2 and 3
Out[7]: 3

In [8]: 0 and 3
Out[8]: 0

3. 循环控制语句 while

循环的重要性主要体现在以下两个方面:

  1. 从编程角度考虑,循环可以避免代码冗余,减少工作量,增强代码可读性,比如:我们需要重复输出某句话 10000 次,不用循环需要写 10000 行 print(),使用循环 2 行代码就可以搞定。
  2. 从用户角度,循环可以提升用户体验,避免不必要的重复操作。比如:我们玩王者的时候,每打完一局,就得重新启动王者,进行登录等操作,那体验就会很差。使用循环,我们就启动一次,直到我们自己按退出,才终止游戏。

Python 中 while 语句实现循环的语法如下:

while expression:
    suite_one
[else:
    suite_two]

说明:只要 expression 为真,就执行 suite_one,再重复判断 expression,直到 expression 为假,终止循环。[] 部分为可选部分,如果 suite_one 中没有出现 break 提前终止循环,suite_two 就会被执行,从而结束循环。注意:即使 suite_one 一次也没有执行,suite_two 也会执行,else 也是循环的一部分。

while...else 测试如下:

while 0:
    print('你好')
else:
    print('循环正常结束!')

结果输出:
循环正常结束!

while 用法示例:

# 打印 10000 次 I love Python!
n = 10000
while n:  # 循环 10000 次后,n = 0, 为假,循环终止
    print('I love Python!')
    n -= 1  # 等价于 n = n - 1
else:
    print('循环正常结束!')

结果输出:
I love Python!
...
...
I love Python!
循环正常结束!

循环中可以使用 continuebreak 两种语句.

  • continue:跳过本次循环剩下的代码,去执行下一次循环的 expression 判断。
  • break:终止循环,去执行循环后的第一句语句。

continuebreak 用法测试:

# 输出 1-10 个数字
print('不使用 continue 和 break,输出结果是:', end='')
n = 0
while n < 10:
    n += 1
    print(n, end=' ')  # end=' ' 是在 n 后面添加空格,默认是 end='\n', 即添加新行
else:
    print()  # 打印空行
    print('不使用 continue 和 break循环结束')

print('使用 continue 输出结果是:', end='')
n = 0
while n < 10:
    n += 1
    if n == 9:
        continue
    print(n, end=' ')  # end=' ' 是在 n 后面添加空格,默认是 end='\n', 即添加新行
else:
    print()  # 打印空行
    print('使用 continue 结束')

print('使用 break 输出结果是:', end='')
n = 0
while n < 10:
    n += 1
    if n == 9:
        break
    print(n, end=' ')  # end=' ' 是在 n 后面添加空格,默认是 end='\n', 即添加新行
else:
    print()  # 打印空行
    print('使用 continue 结束')

结果输出:
不使用 continue 和 break,输出结果是:1 2 3 4 5 6 7 8 9 10
不使用 continue 和 break循环结束
使用 continue 输出结果是:1 2 3 4 5 6 7 8 10
使用 continue 结束
使用 break 输出结果是:1 2 3 4 5 6 7 8
Process finished with exit code 0

我们可以看到,使用了 continue 会跳过输出 9,但是还是会 执行 elsesuite;使用了 break 会直接终止循环,9 和 10 都不会输出,同时也不会执行 elsesuite

循环虽然很强大,但它也有副作用,导致死循环的出现。下面就是一个死循环:

n = 0
while n < 10:
    if n == 9:
        continue
    n += 1
    print(n, end=' ')  # end=' ' 是在 n 后面添加空格,默认是 end='\n', 即添加新行

上面的代码就会进入死循环,因为 当 n == 9 时,执行 continue 语句,跳过后面的 n += 1print(n, end=' '),开始下一次的循环判断。n = 9,所以 n < 10 成立,执行 if 语句,n == 9 成立,执行 continue 语句,又跳过后面的 n += 1print(n, end=' ')。 导致 n 一直是 9,n < 10 始终成立,从而进入死循环。

所以我们在写循环时要注意以下几点:

  1. 判断条件初始值写在循环体外面。
  2. 设置循环结束条件。
  3. 写完循环后,最好测试一下,看看会不会导致死循环。

4. 循环控制语句 for

在 Python 中 for 语句也可以用于循环,它也是运用最多的循环方式,并且它的遍历功能非常强大。遍历是指把所有元素按顺序一个一个访问。for 语句可以遍历序列的元素,比如字符串、元组、列表等,或者其他可迭代对象。可迭代对象是指可以用 for 去遍历每一个元素的对象,比如 strtuplelist这些都属于可迭代对象。

在 Python 中 for 的语法是:

for target_list in expression_list:
    suite_one
[else:
    suite_two]

说明:expression_list 只会被计算一次,并且生成一个可迭代对象。每次按顺序从可迭代对象 expression_list 中取出一个值,并赋值给 target_list,然后执行 suite_one 代码块,不断重复这个过程,直到 expression_list 为空(即取完所有元素)或者引发 StopIteration 异常,最后会执行 else 部分的 suite_two,从而结束循环。[] 部分是可选的,可以不写。

for 中我们也可以使用 continuebreak 语句,用法和在 while 中一样,这里不再展开。

for 用法示列:

# for 用法示例
print('使用 for 遍历字符串:')
for i in 'Python':  # 遍历字符串
    print(i, end=' ')  # end=' ' 在 i 后面添加一个空格

print('\n' + '使用 for 遍历列表:')
for i in [1, 2, 3]:  # 遍历列表
    print(i, end=' ')  # end=' ' 在 i 后面添加一个空格

print('\n' + '使用 for 遍历元组:')
for i in (4, 5, 6):  # 遍历元组
    print(i, end=' ')  # end=' ' 在 i 后面添加一个空格

print('\n' + '使用 for 遍历可迭代对象 range(10):')
for i in range(10):  # 遍历可迭代对象 range(10)
    print(i, end=' ')  # end=' ' 在 i 后面添加一个空格
else:  # 这个 else 匹配离它最近的 for
    print('\n' + 'for 遍历可迭代对象 range(10) 结束!')

输出结果:
使用 for 遍历字符串:
P y t h o n
使用 for 遍历列表:
1 2 3
使用 for 遍历元组:
4 5 6
使用 for 遍历可迭代对象 range(10):
0 1 2 3 4 5 6 7 8 9
for 遍历可迭代对象 range(10) 结束!

这里出现range()函数。range()函数经常和 for 配合使用。
比如上面的 while 打印 10000 次 I love Python!,使用 range()for 配合,两行代码就可以搞定! 代码如下:

# 打印 10000 次 I love Python!
for i in range(10000):
    print('I love Python!')

结果输出:
I love Python!
...
...
I love Python!

注意for 去遍历可迭代对象时,会生成一个内部计数器。这个内部计数器用于追踪下一个要迭代的元素,并且会随着每次迭代递增。当我们用 for 遍历一个可变序列,比如 list 时,如果在 suite 部分对 list 的部分进行了修改,可能会导致灾难性的 bug。具体情况如下:

  1. 如果在遍历 list 时,在 suite 部分删除了该 list 中正在遍历的元素或者它前面的元素,那么当前遍历元素的下一个元素将会被跳过。
  2. 如果在遍历 list 时,在 suite 部分往该 list 中正在遍历的元素之前添加一个元素,那么当前遍历元素的将会被再次遍历。

情况一测试代码如下:

# 移除列表中的所有 2
list_a = [1, 2, 2, 3, 4]
for i in list_a:
    if i == 2:
        list_a.remove(i)  # 移除一个 2
    print(i)
print(list_a)

输出结果:
1
2
3
4
[1, 2, 3, 4]

可以发现,只有一个 2 被替换了。第 2 个 2 被跳过了。这个例子不是很好,只是为了说明这个知识点。移除列表所有 2 更好的方法是用列表推导式 [i for i in list_a if i != 2]。使用列表推导式可以帮我们生成一个列表。

情况二测试代码如下:

# 遍历列表,当列表中出现 2 时,往列表头部添加一个 4
list_a = [1, 2, 3]
for i in list_a:
    if i == 2:
        list_a.insert(0, 4)  # i == 2 时,在列表头部添加一个 4
    print(i)
print(list_a)

结果输出:
1
2
2
...

这段代码会一直往 list_a 的头部添加一个 4,直到计算机奔溃。

这种情况怎么避免呢?我们可以通过切片创建拷贝来解决这个问题。
上面的代码可以修改如下:

情况一修改后代码:

# 移除列表中的所有 2
list_a = [1, 2, 2, 3, 4]
for i in list_a[:]:
    if i == 2:
        list_a.remove(i)
    print(i)
print(list_a)

结果输出:
1
2
2
3
4
[1, 3, 4]

情况二修改后代码:

# 遍历列表,当列表中出现 2 时,往列表头部添加一个 4
list_a = [1, 2, 3]
for i in list_a[:]:
    if i == 2:
        list_a.insert(0, 4)  # i == 2 时,在列表头部添加一个 4
    print(i)
print(list_a)

输出结果:
1
2
3
[4, 1, 2, 3]

所以,用 for 遍历一个可变的可迭代对象时,如果要对可迭代对象进行修改操作,一定要利用切片进行拷贝,利用 for 遍历拷贝。

学完这部分,我们对于 Python 中的流程控制已经基本掌握,能够编写并看懂一些简单的 Python 代码。后面将对 Python 中的函数进行总结。编程需要不断地敲代码,不断地去写才能慢慢的掌握。