Python 3.7从零开始学
上QQ阅读APP看书,第一时间看更新

6.6 循环

程序在一般情况下是按顺序执行的。编程语言提供了各种控制结构,允许更复杂的执行路径。循环语句允许我们多次执行一个语句或语句组。图6-6所示为大多数编程语言中循环语句的执行流程。

我们已经知道条件为真(或假)时程序如何执行了。若想让程序重复执行,该怎么办呢?比如输出1~100所有数字,是写100个输出语句吗?显然你不想这样做。接下来我们学习如何解决这个问题。

图6-6 循环语句执行流程

6.6.1 while循环

我们先看如何使用简单的程序输出1~100所有数字,程序如下(文件命名while_use.py):

     #! /usr/bin/python3
     # -*- coding:UTF-8 -*-

n=1 while n<=100: print(f'当前数字是:{n}') n += 1

由输入程序看到,只需短短几行就可以实现这个功能,我们看输出结果(由于全部输出会太长,也没有必要,因此此处显示几行输出结果作为展示):

     当前数字是: 1
     当前数字是: 2
     当前数字是: 3
     当前数字是: 4
     当前数字是: 5
     ……

由输出结果看到,按顺序输出了对应结果。

该示例中使用了while关键字。在Python编程中,while语句用于循环执行程序,以处理需要重复处理的任务。基本语法形式为:

while判断条件:

执行语句……

执行语句可以是单个语句或语句块。判断条件可以是任何表达式,所有非零、非空(null)的值都为真(true)。当判断条件为假(false)时,循环结束。

while循环的执行流程如图6-7所示。

图6-7 while循环的执行流程

该流程图的意思为:首先对while条件判定,当条件为true时,执行条件语句块,执行完语句块再判定while条件,若仍然为true,则继续执行语句块,直到条件为false时结束循环。

6.6.2 for循环

我们在6.6.1小节讲述了while循环,可以看到while语句非常灵活,例如(exp_while.py):

     #! /usr/bin/python3
     # -*- coding:UTF-8 -*-

n=0 fields=['a','b','c'] while n<len(fields): print(f'当前字母是:{fields[n]}') n += 1

该代码实现的功能是将列表中的元素分别输出。该程序的实现没有什么问题,我们是否有更好的方式实现这个功能呢?答案是有,例如(for_use.py):

     #! /usr/bin/python3
     # -*- coding:UTF-8 -*-

fields=['a','b','c'] for f in fields: print(f'当前字母是:{f}')

可以看到,代码比前面使用while循环时更简洁,代码量也更少。程序执行的输出结果如下:

     当前字母是: a
     当前字母是: b
     当前字母是: c

该示例使用了for关键字。在Python中,for关键字叫作for循环,for循环可以遍历任何序列的项目,如一个列表或字符串。

for循环的语法格式如下:

for iterating_var in sequence:

statements(s)

sequence是任意序列,iterating_var是序列中需要遍历的元素,statements是待执行的语句块。

for循环的执行流程如图6-8所示。

图6-8 for循环的执行流程

该流程图的意思为:首先对for条件判定,游标(后面会详细讲解这个词)指向第0个位置,即指向第一个元素,看sequence序列中是否有元素,若有,则将元素值赋给iterating_var,接着执行语句块,若语句块中需要获取元素值,则使用iterating_var的值,执行完语句块后,将序列的游标往后挪一个位置,再判定该位置是否有元素,若仍然有元素,则继续执行语句块,然后序列的游标再往后挪一个位置,直到下一个位置没有元素时结束循环。

我们再看以下示例(exp_for.py):

     #! /usr/bin/python3
     # -*- coding:UTF-8 -*-

print('-----for循环字符串-----------') for letter in 'good': #for循环字符串 print (f'当前字母 :{letter}')
print('-----for循环数字序列-----------') number=[1,2,3] for num in number: #for循环数字序列 print(f'当前数字:{num}')
print('-----for循环字典-----------') tups={'name':'小智','number':'1002'} for tup in tups: #for循环字典 print(f'{tup}:{tups[tup]}')

输出结果如下:

     -----for循环字符串-----------
     当前字母 : g
     当前字母 : o
     当前字母 : o
     当前字母 : d
     -----for循环数字序列-----------
     当前数字: 1
     当前数字: 2
     当前数字: 3
     -----for循环字典-----------
     number:1002
     name:小智

由上面的输入代码和输出结果可以看到,for循环的使用还是比较方便的。

提 示

如果能使用for循环,就尽量不要使用while循环。

6.6.3 循环遍历字典元素

在6.6.2小节的示例中我们已经提供了使用for循环遍历字典的代码,代码如下(for_in.py):

     tups={'name':'小智','number':'1002'}
     for tup in tups:   #for循环字典
         print(f'{ tup }:{ tups[tup]}')

可以看到,此处用for循环对字典的处理看起来有一些繁杂,是否可以使用更直观的方式处理字典呢?

还记得我们前面学习的序列解包吗?for循环的一大好处是可以在循环中使用序列解包,例如(for_items.py):

     tups={'name':'小智','number':'1002'}
     for key,value in tups.items():
         print(f'{key}:{value}')

输出结果如下:

     number:1002
     name:小智

由输入代码和输出结果看到,可以使用items方法将键-值对作为元组返回。

提 示

字典中的元素是没有顺序的。也就是说,迭代时字典中的键和值都能保证被处理,但是处理顺序不确定。这也是用for循环输出字典中的元素时不按照顺序输出的原因。

6.6.4 迭代工具

在Python中,迭代序列或其他可迭代对象时,有一些函数非常有用。下面我们介绍一些有用的函数。

1. 并行迭代

程序可以同时迭代两个序列,输入如下(iterative_use.py):

     #! /usr/bin/python3
     #-*- coding:UTF-8 -*-

student=['xiaomeng','xiaozhi','xiaoqiang'] number=[1001,1002,1003] for i in range(len(student)): print(f'{student[i]}的学号是:{number[i]}')

程序执行结果如下:

     xiaomeng 的学号是:1001
     xiaozhi 的学号是:1002
     xiaoqiang 的学号是:1003

在程序中,i是循环索引的标准变量名。

在Python中,内建的zip函数用来进行并行迭代,可以把两个序列合并在一起,返回一个元组的列表,例如(zip_func_use.py):

     #! /usr/bin/python3
     #-*- coding:UTF-8 -*-

student=['xiaomeng','xiaozhi','xiaoqiang'] number=[1001,1002,1003] for name,num in zip(student,number): print(f'{name}的学号是:{num}')

程序执行结果和前面一样。

zip函数可以作用于任意数量的序列,并且可以应付不等长的序列,当短序列“用完”时就会停止,例如(zip_exp.py):

     #! /usr/bin/python3
     #-*- coding:UTF-8 -*-

for num1,num2 in zip(range(3),range(100)): print(f'zip键值对为:{num1}{num2}')

程序执行结果如下:

     zip键值对为: 0 0
     zip键值对为: 1 1
     zip键值对为: 2 2

由输出结果看到,zip函数以短序列为准,当短序列遍历结束时,for循环就会遍历结束。

提 示

此处用到的range函数是Python 3中的函数,在Python 2版本中存在与这个函数功能类似的xrange函数。

2. 翻转和排序迭代

我们在列表中学习过reverse和sort方法,此处介绍两个类似的函数——reversed和sorted函数。这两个函数可作用于任何序列或可迭代对象,但不是原地修改对象,而是返回翻转或排序后的版本。在交互模式下输入:

     >>> sorted([5,3,7,1])
     [1, 3, 5, 7]
     >>> sorted('hello,world!')
     ['!', ',', 'd', 'e', 'h', 'l', 'l', 'l', 'o', 'o', 'r', 'w']
     >>> list(reversed('hello,world!'))
     ['!', 'd', 'l', 'r', 'o', 'w', ',', 'o', 'l', 'l', 'e', 'h']
     >>> ''.join(reversed('hello,world!'))
     '!dlrow,olleh'

由输出结果我们看到,sorted函数返回的是一个列表,reversed函数返回的是一个可迭代对象。它们的具体含义不用过多关注,在for循环和join方法中使用不会有任何问题。如果要对这两个函数使用索引、分片及调用list方法,就可以使用list类型转换返回对象。

6.6.5 跳出循环

我们在前面的示例中讲过,循环会一直执行,直到条件为假或序列元素用完时才会结束。若我们想提前中断循环,比如循环的结果已经是我们想要的了,不想让循环继续执行而占用资源,有什么方法可以实现呢?

Python提供了break、continue等语句可用于这种情形。

1. break

break语句用来终止循环语句,即使循环条件中没有False条件或序列还没有遍历完,也会停止执行循环语句。

break语句用在while和for循环中。

如果使用嵌套循环,break语句就会停止执行最深层的循环,并开始执行下一行代码。

break语句语法如下:

break

break语句的执行流程如图6-9所示。

图6-9 break执行流程

当遇到break语句时,无论执行什么条件,都跳出这个循环,例如(break_use.py):

     #! /usr/bin/python3
     #-*- coding:UTF-8 -*-

for letter in 'hello': #示例1 if letter == 'l': break print (f'当前字母为:{letter}')
num = 10 #示例2 while num > 0: print (f'输出数字为:{num}') num -= 1 if num == 8: break

输出结果如下:

     当前字母为: h
     当前字母为: e
     输出数字为: 10
     输出数字为: 9

由输出结果看到,在示例1中,输出语句输出循环遍历到的字符,当遇到指定字符时,跳出for循环。在示例2中,使用while做条件判定,在语句块中输出满足条件的数字,当数字等于8时,跳出while循环,不再继续遍历。

2. continue

continue语句用来告诉Python跳过当前循环的剩余语句,然后继续进行下一轮循环。

continue语句用在while和for循环中。

continue语句的语法格式如下:

continue

continue语句的执行流程如图6-10所示。

当执行过程中遇到continue语句时,无论执行条件是真还是假,都跳过这次循环,进入下一次循环,例如(continue_use.py):

图6-10 continue执行流程

     #! /usr/bin/python3
     #-*- coding:UTF-8 -*-

for letter in 'hello': # 示例1 if letter == 'l': continue print(f'当前字母 :{letter}')
num = 3 # 示例2 while num > 0: num -= 1 if num == 2: continue print (f'当前变量值 :{num}')

输出结果如下:

     当前字母 : h
     当前字母 : e
     当前字母 : o
     当前变量值 : 1
     当前变量值 : 0

由输出结果看到,相比于break语句,使用continue语句只是跳过一次循环,不会跳出整个循环。

6.6.6 循环中的else子句

在开发过程中,可能需要在while、for等循环不满足条件时做一些工作。该怎么实现呢?下面进行介绍。

1. 在while循环中使用else语句

在while条件语句为false时,执行else的语句块,例如(while_else_use.py):

     #! /usr/bin/python3
     #-*- coding:UTF-8 -*-

num = 0 while num < 3: print (f"{num} 小于 3") num += 1 else: print (f"{num} 大于或等于 3") print("结束循环!")

执行结果如下:

     0  小于 3
     1  小于 3
     2  小于 3
     3  大于或等于 3
     结束循环!

由输出结果看到,while循环结束后执行了else语句中的语句块,输出“3大于或等于3”语句。

2. 在for循环中使用else语句

在for条件语句为false或结束后没有被break中断时,执行else的语句块,例如(for_else_use.py):

     #! /usr/bin/python3
     #-*- coding:UTF-8 -*-

names = ['xiaomeng', 'xiaozhi'] for name in names: if name == "xiao": print(f"名称:{name}") break print(f"循环名称列表 {name}") else: print("没有循环数据!") print("结束循环!")

程序执行结果如下:

     循环名称列表 xiaomeng
     循环名称列表 xiaozhi
     没有循环数据!
     结束循环!

由输出条件看到,for循环结束后执行了else语句块中的内容。