我心中的王者:Python-第7章 循环设计

我心中的王者:Python-第7章 循环设计

假设现在笔者要求读者设计一个1加到10的程序,然后打印结果,读者可能用下列方式设计这个程序。

程序实例ch7_1.py:从1加到10,同时打印结果。

# ch7_1.py
sum = 1+2+3+4+5+6+7+8+9+10
print("总和 = ", sum)

执行结果

总和 =  55

如果现在笔者要求各位从1加到100或1000,此时,若是仍用上述方法设计程序,就显得很不现实。

另一种状况,如果一个数据库列表内含有1000名客户的名字,现在要举办晚宴,所以要打印客户姓名,如果用下列方式设计,将是很不实际的行为。

程序实例ch7_2.py:一个不完整且不切实际的程序。

# ch7_2.py -- 不完整的程序
vipNames = ['James','Linda','Peter', ... , 'Kevin']
print("客户1 = ", vipNames[0])
print("客户2 = ", vipNames[1])
print("客户3 = ", vipNames[2])
...
...
print("客户999 = ", vipNames[999])

你的程序可以要写超过1000行,当然碰上这类问题,是不可能用上述方法处理的,不过幸好Python语言提供我们解决这类问题的方式,可以轻松用循环解决,这也是本章的主题。

7-1 基本for循环

for循环可以让程序将整个对象内的元素遍历(也可以称迭代),在遍历期间,同时可以纪录或输出每次遍历的状态或称轨迹。for循环基本语法格式如下:

 for var in 可迭代对象:  # 可迭代对象英文是iterable object
     程序代码区块

可迭代对象(iterable object)可以是列表、元组、字典与集合或range( ),在信息科学中迭代(iteration)可以解释为重复执行,上述语法可以解释为将可迭代对象的元素当作var,重复执行,直到每个元素皆被执行一次,整个循环才会停止。

设计上述程序代码时,必须要留意缩排的问题,可以参考if叙述观念。由于这里笔者介绍列表(list),所以读者可以想象这个可迭代对象(iterable)是列表(list),第8章笔者会讲解元组(Tuple),第9章会讲解字典(Dict),第10章会讲解集合(Set)。另外,上述for循环的可迭代对象也常是range( )函数产生的可迭代对象,将在7-2节说明。

7-1-1 for循环基本运作

例如,一个NBA球队有5位球员,分别是Curry、Jordan、James、Durant、Obama,现在想列出这5位球员,那么使用for循环执行这个工作就很适合。

程序实例ch7_3.py:列出球员名称。

# ch7_3.py
players = ['Curry', 'Jordan', 'James', 'Durant', 'Obama']
for player in players:
    print(player)

执行结果

Curry
Jordan
James
Durant
Obama

上述程序执行的观念是,当第一次执行下列语句时:

 for player in players:

player的内容是‘Curry’,然后执行print(player),所以会印出‘Curry’。由于列表players内还有其他的元素尚未执行,所以会执行第二次,当执行第二次下列语句时:

   for player in players:

player的内容是‘Jordan’,然后执行print(player),所以会印出‘Jordan’。由于列表players内还有其他的元素尚未执行,所以会执行第三次,第四次,当执行第五次下列语句时:

 for player in players:

player的内容是‘Obama’,然后执行print(player),所以会印出‘Obama’。第六次要执行for循环时,由于列表players内所有元素已经执行,所以这个循环就算执行结束。下列是循环的流程示意图。

在这里插入图片描述

7-1-2 如果程序代码区块只有一行

使用for循环时,如果程序代码区块只有一行,它的语法格式可以用下列方式表达:

 for var in 可迭代对象:程序代码区块

程序实例ch7_4.py:重新设计ch7_3.py。

# ch7_4.py
players = ['Curry', 'Jordan', 'James', 'Durant', 'Obama']
for player in players:print(player)

执行结果 与ch7_3.py相同。

7-1-3 有多行的程序代码区块

如果for循环的程序代码区块有多行程序时,要留意这些语句同时需要做缩排处理。它的语法格式可以用下列方式表达:

 for var in 可迭代对象:
 程序代码
 程序代码
 ……

程序实例ch7_5.py:这个程序在设计时,首先笔者将列表的元素英文名字全部改成小写,然后for循环的程序代码区块有2行,这2行(第4和5行)皆需内缩处理,player.title( )的title( )方法可以处理第一个字母以大写显示。

# ch7_5.py
players = ['curry', 'jordan', 'james', 'durant', 'obama']
for player in players:
    print(player.title( ) + ", it was a great game.")
    print("I can not wait to see your next game, " + player.title( ))

执行结果

Curry, it was a great game.
I can not wait to see your next game, Curry
Jordan, it was a great game.
I can not wait to see your next game, Jordan
James, it was a great game.
I can not wait to see your next game, James
Durant, it was a great game.
I can not wait to see your next game, Durant
Obama, it was a great game.
I can not wait to see your next game, Obama

7-1-4 将for循环应用在列表区间元素

Python也允许将for循环应用在6-1-2节和6-1-3节所截取的区间列表元素上。

程序实例ch7_6.py:列出列表前3位和后3位的球员名称。

# ch7_6.py
players = ['Curry', 'Jordan', 'James', 'Durant', 'Obama']
print("打印前3位球员")
for player in players[:3]:
    print(player)
print("打印后3位球员")
for player in players[-3:]:
    print(player)

执行结果

打印前3位球员
Curry
Jordan
James
打印后3位球员
James
Durant
Obama

这个观念其实很有用,例如,你设计一个学习网站,想要每天列出前3名学生基本数据同时表扬,可以将每个人的学习成果放在列表内,同时用降幂排序方式处理,最后可用本节观念列出前3名学生资料。

注:升幂是指由小到大排列。降幂是指由大到小排列。

7-1-5 将for循环应用在数据类别的判断

程序实例ch7_7.py:有一个files列表内含一系列文件名,请将“.py”的Python程序另外建立到py列表,然后打印。

# ch7_7.py
n = 5
number1 = list(range(n))
print("当n值是%d时的range( )列表 = " % n, number1)
n = 8
number2 = list(range(n))
print("当n值是%d时的range( )列表 = " % n, number2)

执行结果

当n值是5时的range( )列表 =  [0, 1, 2, 3, 4]
当n值是8时的range( )列表 =  [0, 1, 2, 3, 4, 5, 6, 7]

程序实例ch7_8.py:有一个列表names,元素内容是姓名,请将姓洪的成员建立在lastname列表内,然后打印。

# ch7_8.py
n = 5
print("当n值是%d时的range( )列表元素:" % n)
for number in range(n):
    print(number)
n = 8
print("当n值是%d时的range( )列表元素:" % n)
for number in range(n):
    print(number)

执行结果

当n值是5时的range( )列表元素:
0
1
2
3
4
当n值是8时的range( )列表元素:
0
1
2
3
4
5
6
7

7-1-6 删除列表内所有元素

程序实例ch7_9.py:Python没有提供删除整个列表元素的方法,不过我们可以使用for循环完成此工作。

# ch7_9.py
start = 2
end = 6
number1 = list(range(start, end))
print("当start值是%2d, end值是%2d时的range( )列表 = " % (start, end), number1)
start = -2
end = 3
number2 = list(range(start, end))
print("当start值是%2d, end值是%2d时的range( )列表 = " % (start, end), number2)
start = -5
end = -1
number3 = list(range(start, end))
print("当start值是%2d, end值是%2d时的range( )列表 = " % (start, end), number3)

执行结果

当start值是 2, end值是 6时的range( )列表 =  [2, 3, 4, 5]
当start值是-2, end值是 3时的range( )列表 =  [-2, -1, 0, 1, 2]
当start值是-5, end值是-1时的range( )列表 =  [-5, -4, -3, -2]

7-2 range( )函数

Python可以使用range( )函数产生一个等差序列,我们又称这等差序列为可迭代对象(iterable object),也可以称是range对象。由于range( )是产生等差序列,我们可以直接使用,将此等差序列当作循环的计数器。

在前一小节我们使用”for var in 可迭代对象”当作循环,这时会使用可迭代对象元素当作循环指针,如果是要迭代对象内的元素,这是好方法,但是如果只是要执行普通的循环迭代,由于可迭代对象占用内存空间,所以这类循环需要占用较多系统资源。这时我们应该直接使用range( )对象,这类迭代只有迭代时的计数指针需要内存,所以可以节省内存空间,range( )的用法与列表的切片(slice)类似。

range(start, stop, step)

上述stop是唯一必须的值,等差序列是产生stop的前一个值。例如:如果省略start,所产生等差序列范围是从0至stop-1。step的预设是1,所以预设等差序列是递增1。如果将step设为2,等差序列是递增2。如果将step设为-1,则是产生递减的等差序列。

由range( )产生的可迭代等差对象的数据类型是range,可参考下列实例。
在这里插入图片描述

下列代码用来打印range( )对象内容。
在这里插入图片描述

上述代码执行循环迭代时,即使是执行3个循环,但是系统不用一次预留3个整数空间储存循环计数指针,而是每次循环用1个整数空间储存循环计数指针,所以可以节省系统资源。下列是range( )含step参数的应用,第1个是建立1~10的奇数序列,第2个是建立每次递减2的序列。

在这里插入图片描述

7-2-1 只有一个参数的range( )函数的应用

当range(n)函数搭配一个参数时:

 range(n)  # 它将产生0, 1, … , n-1的可迭代对象内容

下面来测试range( )方法。

程序实例ch7_10.py:输入数字,本程序会将此数字当作打印星号的数量。

# ch7_10.py
start = 2
end = 6
print("当start值是%d, end值是%d时的range( )列表元素:" % (start, end))
for number in range(start,end):
    print(number)
start = -2
end = 3
print("当start值是%d, end值是%d时的range( )列表元素:" % (start, end))
for number in range(start,end):
    print(number)
start = -5
end = -1
print("当start值是%d, end值是%d时的range( )列表元素:" % (start, end))
for number in range(start,end):
    print(number)

执行结果

当start值是2, end值是6时的range( )列表元素:
2
3
4
5
当start值是-2, end值是3时的range( )列表元素:
-2
-1
0
1
2
当start值是-5, end值是-1时的range( )列表元素:
-5
-4
-3
-2

7-2-2 有2个参数的range( )函数

当range( )函数搭配2个参数时,它的语法格式如下:

  range(start, end))  # start是起始值,end-1是终止值

上述可以产生start起始值到end-1终止值之间每次递增1的序列,start或end可以是负整数,如果终止值小于起始值则产生空序列或称空range对象,可参考下列程序实例。
在这里插入图片描述

下列代码是使用负值当作起始值。
在这里插入图片描述

程序实例ch7_11.py:输入正整数值n,这个程序会计算从0加到n之值。

# ch7_11.py
start = 2
end = 9
step = 2
number1 = list(range(start, end, step))
print("当start值是%2d, end值是%2d, step值是%2d时的range( )列表 = " % (start, end, step), number1)
start = -2
end = 9
step = 3
number2 = list(range(start, end, step))
print("当start值是%2d, end值是%2d, step值是%2d时的range( )列表 = " % (start, end, step), number2)
start = 5
end = -5
step = -3
number3 = list(range(start, end, step))
print("当start值是%2d, end值是%2d, step值是%2d时的range( )列表 = " % (start, end, step), number3)

执行结果

当start值是 2, end值是 9, step值是 2时的range( )列表 =  [2, 4, 6, 8]
当start值是-2, end值是 9, step值是 3时的range( )列表 =  [-2, 1, 4, 7]
当start值是 5, end值是-5, step值是-3时的range( )列表 =  [5, 2, -1, -4]

7-2-3 有3个参数的range( )函数

当range( )函数搭配3个参数时,它的语法格式如下:

range(start, end, step) #  start是起始值,end是终止值,step是间隔值

然后会从起始值开始产生等差数列,每次间隔step时产生新数值元素,到end-1为止,下列是产生2~11间的偶数。
在这里插入图片描述

此外,step值也可以是负值,此时起始值必须大于终止值。

在这里插入图片描述

7-2-4 活用range( )应用

程序设计时我们也可以直接应用range( ),可以产生程序精简的效果。

程序实例ch7_12.py:输入一个正整数n,这个程序会输出从1加到n的总和。

# ch7_12.py
start = 2
end = 9
step = 2
number1 = list(range(start, end, step))
print("当start值是%2d, end值是%2d, step值是%2d时的range( )列表元素:" % (start, end, step))
for number in range(start,end,step):
    print(number)
start = -2
end = 9
step = 3
number2 = list(range(start, end, step))
print("当start值是%2d, end值是%2d, step值是%2d时的range( )列表元素:" % (start, end, step))
for number in range(start,end,step):
    print(number)
start = 5
end = -5
step = -3
number3 = list(range(start, end, step))
print("当start值是%2d, end值是%2d, step值是%2d时的range( )列表元素:" % (start, end, step))
for number in range(start,end,step):
    print(number)

执行结果

当start值是 2, end值是 9, step值是 2时的range( )列表元素:
2
4
6
8
当start值是-2, end值是 9, step值是 3时的range( )列表元素:
-2
1
4
7
当start值是 5, end值是-5, step值是-3时的range( )列表元素:
5
2
-1
-4

上述程序笔者使用了可迭代对象的内置函数sum执行总和的计算,它的工作原理并不是一次预留储存1, 2, … 10的内存空间,然后执行运算,而是只有一个内存空间,每次将迭代的指针放在此空间,然后执行sum( )运算,可以增加工作效率并节省内存空间。

程序实例ch7_13.py:建立一个整数平方的列表,为了避免数值太大,若是输入值大于10,此大于10的数值将被设为10。

# ch7_13.py
n = int(input("请输入整数:"))
number = list(range(n + 1))
total = sum(number)
print("从1到%d的总和是 = " % n, total)

执行结果

请输入整数:12112的总和是 =  78

对于上述代码而言,下面我们使用“**”代替乘方运算,同时第6和第7行使用更精简的方式。

程序实例ch7_14.py:用更精简方式设计ch7_13.py。

# ch7_14.py
n = int(input("请输入整数:"))
number = list(range(n + 1))       # 建立列表
total = 0                         # 总计
for i in number:
    total += i
print("从1到%d的总和是 = " % n, total)

执行结果 与ch7_13.py相同。

7-2-5 列表生成(list generator)的应用

其实我们还可以进一步简化程序实例ch7_14.py,这个方式是将for循环与加入列表的代码浓缩为一行,对上述程序而言,可以将第5和6行浓缩为一行,在说明实例前先看基本语法。基本语法如下:

  新列表 = [表达式  for  项目  in  可迭代对象]

上述语法观念是,将每个可迭代对象套入表达式,每次产生一个列表元素。如果将第5~6行转成上述语法,内容如下:

  square = [num ** 2 for num in range(1, n+1)]

此外,用这种方式设计时,我们可以省略第2行(建立空列表)。

程序实例ch7_15.py:重新设计ch7_14.py,进阶列表生成的应用。

# ch7_15.py
n = int(input("请输入整数:"))
total = 0                         # 总计
for i in range(1, n+1):
    total += i
print("从1到%d的总和是 = " % n, total)

执行结果 与ch7_14.py相同。

程序实例ch7_16.py:毕达哥拉斯直角三角形(A Pythagorean triple)定义,其实这是中学数学的勾股定理,基本观念是直角三角形两边长的平方和等于斜边的平方,如下:

a2 + b2 = c2  # c是斜边长

这个定理我们可以用(a, b, c)方式表达,最著名的实例是(3,4,5),小括号是数组的表达方式,我们尚未介绍,所以本节使用[a,b,c]列表表示。这个程序会生成0~19间符合定义的a、b、c列表值。

# ch7_16.py
squares = []                     # 建立空列表
n = int(input("请输入整数:"))
if n > 10 : n = 10               # 最大值是10
for num in range(1, n+1):        
    value = num * num            # 元素平方
    squares.append(value)        # 加入列表
print(squares)

执行结果

请输入整数:12
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

程序实例ch7_17.py:在数学的使用中会碰上下列数学定义。

   A * B = {(a, b)}:a 属于A元素,b属于B元素

我们可以用下列程序生成这类的列表。

# ch7_17.py
squares = []                     # 建立空列表
n = int(input("请输入整数:"))
if n > 10 : n = 10               # 最大值是10
for num in range(1, n+1):        
    squares.append(num ** 2)     # 加入列表
print(squares)

执行结果

请输入整数:12
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

7-2-6 打印含列表元素的列表

这个小节的观念称为list unpacking,这个程序会从每个列表中拉出color和shape的列表元素值。

程序实例ch7_18.py:简化上一个程序,然后列出列表内每个元素列表值。

# ch7_18.py
n = int(input("请输入整数:"))
if n > 10 : n = 10               # 最大值是10
squares = [num ** 2 for num in range(1, n+1)]
print(squares)

执行结果

请输入整数:12
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

7-2-7 生成含有条件的列表

这时语法如下:

新列表 = [表达式 for 项目 in 可迭代对象 if 条件式]

下列是用传统方式生成1, 3, … , 9的列表:
在这里插入图片描述

下列是使用Python精神,设计含有条件式的列表生成程序。
在这里插入图片描述

7-3 进阶的for循环应用

7-3-1 嵌套for循环

一个循环内有另一个循环,我们称这是嵌套循环。如果外循环要执行n次,内循环要执行m次,则整个循环执行的次数是n*m次,设计这类循环时要特别注意下列事项:

外层循环的索引值与内层循环的索引值必须不同。

程序代码的内缩一定要小心。
下列是嵌套循环基本语法:

for 变量 in 对象:       # 外层for循环for 变量 in 对象:  # 内层for循环

下列将用实例说明。

程序实例ch7_19.py:打印9*9的乘法表。

# ch7_19.py
for i in range(1, 10):
    for j in range(1, 10):
        result = i * j
        print("%d*%d=%-3d" % (i, j, result), end=" ")
    print()         # 换行输出

执行结果

1*1=1   1*2=2   1*3=3   1*4=4   1*5=5   1*6=6   1*7=7   1*8=8   1*9=9   
2*1=2   2*2=4   2*3=6   2*4=8   2*5=10  2*6=12  2*7=14  2*8=16  2*9=18
3*1=3   3*2=6   3*3=9   3*4=12  3*5=15  3*6=18  3*7=21  3*8=24  3*9=27
4*1=4   4*2=8   4*3=12  4*4=16  4*5=20  4*6=24  4*7=28  4*8=32  4*9=36
5*1=5   5*2=10  5*3=15  5*4=20  5*5=25  5*6=30  5*7=35  5*8=40  5*9=45
6*1=6   6*2=12  6*3=18  6*4=24  6*5=30  6*6=36  6*7=42  6*8=48  6*9=54
7*1=7   7*2=14  7*3=21  7*4=28  7*5=35  7*6=42  7*7=49  7*8=56  7*9=63
8*1=8   8*2=16  8*3=24  8*4=32  8*5=40  8*6=48  8*7=56  8*8=64  8*9=72
9*1=9   9*2=18  9*3=27  9*4=36  9*5=45  9*6=54  9*7=63  9*8=72  9*9=81

上述程序第5行,%-3d主要是供result使用,表示每一个输出预留3格,同时靠左输出。同一行End=“”则是设定,输出完空一格,下次输出不换行输出。当内层循环执行完一次,则执行第6行,这是外层循环叙述,主要是设定下次换行输出,相当于下次再执行内层循环时换行输出。

程序实例ch7_20.py:绘制直角三角形。

# ch7_20.py
for i in range(1, 10):
    for j in range(1, 10):
        if j <= i:
            print("aa", end="")
    print()                # 换行输出

执行结果

aa
aaaa
aaaaaa
aaaaaaaa
aaaaaaaaaa
aaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaa

7-3-2 强制离开for循环-break指令

在设计for循环时,如果期待某些条件发生时可以离开循环,可以在循环内执行break指令,即可立即离开循环,这个指令通常是和if语句配合使用。下列是常用的语法格式:

在这里插入图片描述

下列是流程图,其中在for循环内的if条件判断,也许前方有程序代码区块1、if条件内有程序代码区块2或是后方有程序代码区块3,只要if条件判断是True,则执行if条件内的程序代码区块2后,可立即离开循环。
在这里插入图片描述

例如,设计一个比赛,可以将参加比赛者的成绩列在列表内,如果想列出前20名参加决赛,可以设定for循环当选取20名后,即离开循环,此时就可以使用break功能。

程序实例ch7_21.py:输出一系列数字元素,当数字为5时,循环将终止执行。

# ch7_21.py
print("测试1")
for digit in range(1, 11):
    if digit == 5:
        break
    print(digit, end=', ')
print( )
print("测试2")
for digit in range(0, 11, 2):
    if digit == 5:
        break
    print(digit, end=', ')  

执行结果

测试1
1, 2, 3, 4,
测试2
0, 2, 4, 6, 8, 10,

上述在第一个列表的测试中(第3至6行),当碰到列表元素是5时,循环将终止,所以只有列出“1, 2, 3, 4,”元素。在第二个列表的测试中(第9至12行),当碰到列表元素是5时,循环将终止,可是这个列表元素中没有5,所以整个循环可以正常执行到结束。

程序实例ch7_22.py:列出球员名称,列出多少个球员则是由屏幕输入,这个程序同时设定,如果屏幕输入的人数大于列表的球员数时,自动将所输入的人数降为列表的球员数。

# ch7_22.py
players = ['Curry', 'Jordan', 'James', 'Durant', 'Obama', 'Kevin', 'Lin']
n = int(input("请输入人数 = "))
if n > len(players) : n = len(players)  # 列出人数不大于列表元素数
index = 0                               # 索引
for player in players:
    if index == n:
        break
    print(player, end=" ")
    index += 1                          # 索引加1

执行结果

请输入人数 = 12
Curry Jordan James Durant Obama Kevin Lin

7-3-3 for循环暂时停止不往下执行–continue指令

在设计for循环时,如果期待某些条件发生时可以不往下执行循环内容,此时可以用continue指令,这个指令通常是和if语句配合使用。下列是常用的语法格式:
在这里插入图片描述

下列是流程图,相当于如果发生if条件判断是True时,则不执行程序代码区块3内容。
在这里插入图片描述

程序实例ch7_23.py:有一个列表scores纪录James的比赛得分,设计一个程序可以列出James有多少场次得分大于或等于30分。

# ch7_23.py
scores = [33, 22, 41, 25, 39, 43, 27, 38, 40]
games = 0
for score in scores:
    if score < 30:                  # 小于30则不往下执行
        continue
    games += 1                      # 场次加1              
print("有%d场得分超过30分" % games)

执行结果

6场得分超过30

程序实例ch7_24.py:有一个列表players,这个列表的元素也是列表,包含球员名字和身高数据,列出所有身高是200(含)公分以上的球员数据。

# ch7_24.py
players = [['James', 202],
           ['Curry', 193],
           ['Durant', 205],
           ['Jordan', 199],
           ['David', 211]]
for player in players:
    if player[1] < 200:
        continue
    print(player)

执行结果

['James', 202]
['Durant', 205]
['David', 211]

对于上述for循环而言,每次执行第7行时,player的内容是players的一个元素,而这个元素是一个列表,例如:第一次执行时player内容是如下:

 [‘James', 202]

执行第8行时,player[1]的值是202。由于if判断的结果是False,所以会执行第10行的print(player)指令,其他可依次类推。

7-3-4 for … else循环

在设计for循环时,如果期待所有的if叙述条件是False时,在最后一次循环后,可以执行特定程序区块指令,可使用这个叙述,这个指令通常是和if和break语句配合使用。下列是常用的语法格式:
在这里插入图片描述

下列是流程图,如果最后一次循环if条件表达式仍是False时,才会执行程序代码区块4。
在这里插入图片描述

其实这个语法很适合传统数学中测试某一个数字n是否是质数,质数的条件是:

  • 2是质数。
  • n不可被2至n-1的数字整除。

程序实例ch7_25.py:质数测试的程序,如果所输入的数字是质数则列出是质数,否则列出不是质数。

# ch7_25.py
num = int(input("请输入大于1的整数做质数测试 = "))
if num == 2:                                # 2是质数所以直接输出
    print("%d是质数" % num)
else:
    for n in range(2, num):                 # 用2 .. num-1当除数测试
        if num % n == 0:                    # 如果整除则不是质数
            print("%d不是质数" % num)
            break                           # 离开循环

    else:                                   # 否则是质数
        print("%d是质数" % num)  

执行结果

请输入大于1的整数做质数测试 = 3
3是质数

7-4 while循环

这也是一个循环,基本上循环会一直执行直到条件运算为False才会离开循环,所以设计while循环时一定要设计一个条件可以离开循环,相当于让循环结束。程序设计时,如果忘了设计条件可以离开循环,程序造成无限循环状态,此时可以同时按Ctrl+C键,中断程序的执行离开无限循环的陷阱。

一般while循环常应用在不知道循环何时可以结束的状况,for循环在使用时是早已经知道循环即将执行的次数。不过我们也可以透过一些技巧,让while循环也可以应用在已经知道循环即将执行的次数上。它的语法格式如下:

  while 条件运算:
          程序区块

下列是while循环语法流程图。
在这里插入图片描述

7-4-1 基本while循环

程序实例ch7_26.py:这个程序会输出你所输入的内容,当输入q时,程序才会执行结束。

# ch7_26.py
msg1 = '人机对话专栏,告诉我心事吧,我会重复你告诉我的心事!'
msg2 = '输入 q 可以结束对话'
msg = msg1 + '\n' + msg2 + '\n' + '= '
input_msg = ''                # 默认为空字符串
while input_msg != 'q':
    input_msg = input(msg)
    print(input_msg)

执行结果

人机对话专栏,告诉我心事吧,我会重复你告诉我的心事!
输入 q 可以结束对话
= 哈哈
哈哈

上述程序最大的缺点是,当输入q时,程序也将输出q,然后才结束while循环,我们可以使用下列第8行增加if条件判断方式改良。

程序实例ch7_27.py:改良程序ch7_26.py,当输入q时,不再输出q。

# ch7_27.py
msg1 = '人机对话专栏,告诉我心事吧,我会重复你告诉我的心事!'
msg2 = '输入 q 可以结束对话'
msg = msg1 + '\n' + msg2 + '\n' + '= '
input_msg = ''                  # 默认为空字符串
while input_msg != 'q':
    input_msg = input(msg)
    if input_msg != 'q':        # 如果输入不是q才输出讯息         
        print(input_msg)

执行结果

输入 q 可以结束对话
= 哈哈
哈哈
人机对话专栏,告诉我心事吧,我会重复你告诉我的心事!
输入 q 可以结束对话
= 呵呵
呵呵
人机对话专栏,告诉我心事吧,我会重复你告诉我的心事!
输入 q 可以结束对话
=

上述程序尽管可以完成工作,但是当我们在设计大型程序时,如果可以有更明确的标记记录程序是否继续执行将更佳,下列笔者将用一个布尔变量值active当作标记,如果是True则while循环继续,否则while循环结束。

程序实例ch7_28.py:改良ch7_27.py程序的可读性,使用标记active记录是否循环继续。

# ch7_28.py
msg1 = '人机对话专栏,告诉我心事吧,我会重复你告诉我的心事!'
msg2 = '输入 q 可以结束对话'
msg = msg1 + '\n' + msg2 + '\n' + '= '
active = True
while active:                   # 循环进行直到active是False
    input_msg = input(msg)
    if input_msg != 'q':        # 如果输入不是q才输出讯息         
        print(input_msg)
    else:
        active = False          # 输入是q所以将active设为False

执行结果 与ch7_27.py相同。

程序实例ch7_29.py:猜数字游戏,程序第2行用变量answer存储欲猜的数字,程序执行时用变量guess存储所猜的数字。

# ch7_29.py
answer = 30                 # 正确数字
guess = 0                   # 设定所猜数字的初始值
while guess != answer:
    guess = int(input("请猜1-100间的数字 = "))
    if guess > answer:
        print("请猜小一点")
    elif guess < answer:
        print("请猜大一点")
    else:
        print("恭喜答对了")

执行结果

请猜1-100间的数字 = 23
请猜大一点
请猜1-100间的数字 = 55
请猜小一点
请猜1-100间的数字 = 50
请猜小一点
请猜1-100间的数字 = 40
请猜小一点
请猜1-100间的数字 = 35
请猜小一点
请猜1-100间的数字 = 30
恭喜答对了

下列是使用while循环,已经知道要执行多少次循环了的实例。

程序实例ch7_30.py:while循环索引值变化的观察。

# ch7_30
index = 1
while index <= 5:
    print("第 %d 次while循环" % index)
    index += 1

执行结果

1while循环
第 2while循环
第 3while循环
第 4while循环
第 5while循环

7-4-2 嵌套while循环

while循环也允许嵌套循环,此时的语法格式如下:

 while 条件运算:      # 外层while循环while 条件运算:  # 内层while循环

程序实例ch7_31.py:使用while循环重新设计ch7_19.py,打印九九乘法表。

# ch7_31.py
i = 1                   # 设定i初始值
while i <= 9:           # 当i大于9跳出外层循环
    j = 1               # 设定j初始值
    while j <= 9:       # 当j大于9跳出内层循环
        result = i * j
        print("%d*%d=%-3d" % (i, j, result), end=" ")
        j += 1          # 内层循环加1
    print()             # 换行输出
    i += 1              # 外层循环加1

执行结果 与ch7_19.py相同。

7-4-3 强制离开while循环-break指令

7-3-2节所介绍的break指令与观念,也可以应用在while循环。在设计while循环时,如果期待某些条件发生时可以离开循环,可以在循环内执行break指令立即离开循环,这个指令通常是和if语句配合使用。下列是常用的语法格式:
在这里插入图片描述

程序实例ch7_32.py:这个程序会先建立while无限循环,如果输入q,则可跳出这个while无限循环。程序内容主要是要求输入水果,然后输出此水果。

# ch7_32.py
msg1 = '人机对话专栏,请告诉我妳喜欢吃的水果!'
msg2 = '输入 q 可以结束对话'
msg = msg1 + '\n' + msg2 + '\n' + '= '
while True:                     # 这是while无限循环
    input_msg = input(msg)
    if input_msg == 'q':        # 输入q可用break跳出循环          
        break
    else:
        print("我也喜欢吃 %s " % input_msg.title( ))  

执行结果

人机对话专栏,请告诉我妳喜欢吃的水果!
输入 q 可以结束对话
= 香蕉
我也喜欢吃 香蕉
人机对话专栏,请告诉我妳喜欢吃的水果!
输入 q 可以结束对话
=

程序实例ch7_33.py:使用while循环重新设计ch7_22.py。

# ch7_33.py
players = ['Curry', 'Jordan', 'James', 'Durant', 'Obama', 'Kevin', 'Lin']
n = int(input("请输入人数 = "))
if n > len(players) : n = len(players)  # 列出人数不大于串行元素数
index = 0                               # 索引index
while index < len(players):             # 是否index在串行长度范围
    if index == n:                      # 是否达到想列出的人数
        break
    print(players[index], end=" ")
    index += 1                          # 索引index加1

执行结果 与ch7_22.py相同。

上述程序第6行的“index < len(players)”相当于是语法格式的条件表达式A,控制循环是否终止。程序第7行的“index == n”相当于是语法格式的条件表达式B,可以控制是否中途离开while循环。

7-4-4 while循环暂时停止不往下执行-continue指令

在设计while循环时,如果期待某些条件发生时可以不往下执行循环内容,此时可以用continue指令,这个指令通常是和if语句配合使用。下列是常用的语法格式:
在这里插入图片描述

程序实例ch7_34.py:列出1至10之间的偶数。

# ch7_34.py
index = 0
while index <= 10:
    index += 1
    if ( index % 2 != 0 ):  # 测试是否奇数
        continue            # 不往下执行
    print(index)            # 输出偶数

执行结果

2
4
6
8
10

7-4-5 while循环条件表达式与对象

while循环的条件表达式也可与对象(列表、元组或字典)配合使用,此时它的语法格式如下:

while 条件表达式:  # 与有关的条件表达式
     程序区块

程序实例ch7_35.py:删除列表内的apple字符串,程序第5行,只要在fruits列表内可以找到变量apple,就会传回True,循环将继续。

# ch7_35.py
fruits = ['apple', 'orange', 'apple', 'banana', 'apple']
fruit = 'apple'
print("删除前的fruits", fruits)
while fruit in fruits:      # 只要列表内有apple循环就继续
    fruits.remove(fruit)
print("删除后的fruits", fruits)

执行结果

删除前的fruits ['apple', 'orange', 'apple', 'banana', 'apple']
删除后的fruits ['orange', 'banana']

程序实例ch7_36.py:有一个列表buyers,此列表内含购买者和消费金额,如果购买金额超过或达到1000元,则归类为VIP买家vipbuyers列表。否则是Gold买家goldbuyers列表。

# ch7_36.py
buyers = [['James', 1030],              # 建立买家购买纪录
           ['Curry', 893],
           ['Durant', 2050],
           ['Jordan', 990],
           ['David', 2110]]
goldbuyers = []                         # Gold买家列表
vipbuyers =[]                           # VIP买家列表
while buyers:                           # 执行买家分类循环分类完成循环才会结束
    index_buyer = buyers.pop()
    if index_buyer[1] >= 1000:          # 用1000圆执行买家分类条件
        vipbuyers.append(index_buyer)   # 加入VIP买家列表
    else:
        goldbuyers.append(index_buyer)  # 加入Gold买家列表
print("VIP 买家资料", vipbuyers)
print("Gold买家资料", goldbuyers)

执行结果

VIP 买家资料 [['David', 2110], ['Durant', 2050], ['James', 1030]]
Gold买家资料 [['Jordan', 990], ['Curry', 893]]

上述程序第9行只要列表不是空列表,while循环就会一直执行。

7-4-6 pass

pass指令是什么事也不做,如果我们想要建立一个无限循环可以使用下列写法。

while  True:   
    pass

不过不建议这么做,这会让程序进入无限循环。这个指令有时候会用在设计一个循环或函数(将在第11-8节解说)尚未完成时,先放pass,未来再用完整程序代码取代。
程序实例ch7_37.py:pass应用在循环的实例,这个程序的循环尚未设计完成,所以笔者先用pass处理。

# ch7_37.py
schools = ['三峡大学', '长江大学', '武汉大学']
for school in schools:
    pass

执行结果 
没有任何数据输出。

7-5 enumerate对象使用for循环解析

延续6-11节的enumerate对象可知,这个对象是由计数值与元素值配对出现: 计数值 元素值
所以我们可以使用for循环将每一个计数值与元素值解析出来。
程序实例ch7_38.py:继续设计ch6_48.py,将enumerate对象的计数值与元素值解析出来。

# ch7_38.py
drinks = {"coffee", "tea", "wine"}
# 解析enumerate物件
for drink in enumerate(drinks):             # 数值初始是0
    print(drink)
for count, drink in enumerate(drinks):
    print(count, drink)
print("****************")   
# 解析enumerate物件
for drink in enumerate(drinks, 10):         # 数值初始是10
    print(drink)
for count, drink in enumerate(drinks, 10):
    print(count, drink)

执行结果

(0, 'wine')
(1, 'tea')
(2, 'coffee')
0 wine
1 tea
2 coffee
****************
(10, 'wine')
(11, 'tea')
(12, 'coffee')
10 wine
11 tea
12 coffee

上述程序第6行观念如下:
在这里插入图片描述

由于enumerate(drinks)产生的enumerate对象是配对存在,可以用2个变量遍历这个对象,只要仍有元素尚未被遍历循环就会继续。

在这里插入图片描述

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值