【Python】第3章 循环语句

目录

3.1   for 循环语句

3.2   break 语句和 continue 语句

3.3   多重循环

3.4   while 循环语句

3.5   异常处理

3.6   调试程序的方法


        有时,需要重复多次执行一系列语句,循环语句就提供这样的功能。Python中的循环语句,有for循环语句和while循环语句两种。

3.1   for 循环语句

        for循环语句格式如下:

for 变量 in 序列:
        语句组1
else:
        语句组2

        先依次对序列中的每个值执行语句组1。然后,再执行语句组2。语句组1被执行的次数称为循环的次数。大多数情况下其实不需要else和语句组2。语句组要缩进。序列可以是range(...),也可以是字符串、列表、元组、字典、集合。例如:

for i in range(4):
    print(i,end = " ")

        程序输出:

0 1 2 3

        range(n)是一个序列,包含整数0,1,2,……,n−1,相当于一个不包含n在内的左闭右开的区间[0,n)。上面的for语句,i依次取range(4)这个区间里面的每个值(0,1,2,3)并输出。

        range(0)是一个空序列。因此下面程序无输出:

for i in range(0):
    print(i)

        range(m,n)则对应于一个不包含n的左闭右开的区间[m,n):

for i in range(5,9):
        print(i,end = " ")
#>>5 6 7 8

        range(n,n)是一个空序列。总之,若n小于等于m,则range(m,n)是空序列。

        range(m,n,s)表示一个序列,m是起点,n是终点,s称为“步长”。序列第一个元素是m,第二个是m+s,第三个是m+2×s……。但是终点n不取。如果m大于n且s是负数,则为从大往小取。

for i in range(0, 10, 3):        #步长为3,即每3个元素取1个
    print(i,end = " ")
#>>0 3 6 9
for i in range(-10, -100, -30):
    print(i,end = " ")
#>>-10 -40 -70

        程序输出:

0 3 6 9 -10 -40 -70

        可以用for循环遍历列表和字符串,即依次访问列表中的每个元素,以及字符串中的每个字符:

a = [123, 'ok', 'pku', 'QQ']
for i in range(len(a)):    #len(a)求列表a长度(元素个数)
    print(i, a[i], end = ",")
#>>0 123,1 ok,2 pku,3 QQ,
print("")    #输出换行
for i in a:
    print(i,end = " ")
#>>123 ok pku QQ
print("")
for letter in 'Taobao':
    print(letter, end="")
#>>Taobao

        第2行:如果x是字符串、列表、元组、字典或集合,len(x)可以求x的长度,即元素个数。比如,len("abc")的值是3。

        第5行:输出空串,等于换行。

        第6、7行:i的值依次取a[0],a[1],……,a[3],输出每个i。因此这个循环输出如第8行所示。

        第10行:letter依次取'Taobao'中的每个字符。

        程序输出:

0 123,1 ok,2 pku,3 QQ,
123 ok pku QQ 
Taobao

         下面是一个带else的for循环的例子:

cities = ["Beijing","Chengdu","Wuhan","Tianjin"]
for city in cities:
    print(city,end = ",")
else:
    print("No break")
print("Done!")

        程序输出:

Beijing,Chengdu,Wuhan,Tianjin,No break
Done!

        可见,在遍历完序列cities中的每个取值以后,才会执行else分支里面的语句组。

        可以用for循环连续输出26个小写字母:

for i in range(26):
    print(chr(ord("a") + i),end="")

        程序输出:

abcdefghijklmnopqrstuvwxyz

        在Python中,每个字符都是长度为1的字符串,每个字符都有一个编码。字符的编码是整数。ord(x)用于求字符x的编码,chr(x)用于求编码为整数x的字符。字符"a"到"z"的编码是连续的,即"a"的编码加上1就是"b"的编码,再加1就得"c"的编码……

        上面这段话提到的编码,都是指Unicode编码。编码有Unicode、UTF-8、ASCII、GBK等多种,在7.2节会详细解释。

        i取值从0到25,因此ord("a")+i依次是"a","b","c",……,"z"的编码,chr(ord("a")+i)自然就依次是"a","b","c",……,"z"。

        "A"到"Z","0"到"9"的编码也是连续的。下面程序的输出是0123456789:

for i in range(10):
    print(chr(ord("0") + i),end="")

3.2   break 语句和 continue 语句

        break语句可以用于从循环中跳出。例如:

cities = ["Beijing","Chengdu","Wuhan","Tianjin"]
for city in cities:
    if city[0] == 'W':
        break
    print(city,end = ",")
else:
    print("No break")
print("Done!")

        程序输出:

Beijing,Chengdu,Done!

        第4行:break导致循环语句立即结束,本次循环语句组中剩余的部分即第5句也不执行。因此,当city等于"Wuhan"时,不打印"Wuhan",for循环直接结束,连else部分都不会被执行。

        continue语句可以立即结束本次循环,开始下一次循环:

for letter in 'Taobao':
    if letter == 'o':    #字母为o时跳过输出
        continue         #直接跳到下次循环
    print(letter,end = "")

        程序输出:

Taba

        第3行:continue导致本次循环立即结束,即语句组里剩下的第4句不执行,直接开始下一次循环,即letter变为下一个字母。所以字母'o'没有被输出出来。

3.3   多重循环

        循环可以嵌套,即循环的语句组里面还可以包含循环,形成多重循环,写法为:

for i in 序列1:
        ......
        for j in 序列2:
                语句组2
        ......

        for i这个循环称为外重循环,for j这个循环称为内重循环。如果序列1是range(n),序列2是range(m),那么语句组2会被执行n×m次。

3.4   while 循环语句

        while语句格式如下:

while 表达式 exp:
        语句组1
else:
        语句组2

        while循环执行步骤如下。

        第1步:判断exp是否为真,若为真,转第2步;若为假,转第3步。

        第2步:执行语句组1,然后回到第1步。

        第3步:执行语句组2。

        第4步:while语句执行完毕,程序继续往下执行。

        一般情况下都不需要写else,而写成如下形式:

while 表达式 exp:
        语句组1

        执行步骤如下。

        第1步:判断exp是否为真,若为真,转第2步;若为假,转第3步。

        第2步:执行语句组1,然后回到第1步。

        第3步:while语句执行完毕,程序继续往下执行。

        连续输出26个字母可以用while循环实现如下:

i = 0
while i < 26:    #只要i<26就执行下面
    print(chr(ord("a") + i),end="")"
    i+=1

        有时会用到下面这种while写法:

whileTrue:
        ……
        if exp:
                break
        ……

        while True就意味着这个循环会不停执行。只有在exp为真,执行break的情况下才会终止循环。

        continue语句同样适用于while循环。

        下面的程序提示用户输入密码,密码不正确则提示不正确,然后再次要求输入密码。密码正确则提示成功,然后结束。密码是pku。

while (input("请输入密码:") != "pku"):
    print("密码不正确!")
print("密码输入成功!")

        程序运行结果可能如下:

        请输入密码:bba↙
        密码不正确!
        请输入密码:
std↙
        密码不正确!
        请输入密码:
pku↙
        密码输入成功!

3.5   异常处理

        程序的运行时错误也称为异常(RuntimeError),会导致程序突然中止,并输出一些表明异常产生原因的信息。这些信息在不懂的人看来十分诡异。引发异常的原因多种多样,下标越界、不正确的转换、除法除数为0、把整数和字符串相加、要打开的文件不存在……Python提供了对异常进行处理的手段,使得程序即便发生异常,也不会中止,而是可以根据程序员的意图继续运行。

        try......except语句用于进行异常处理,其基本写法是:

try:
        语句组1
except Exception as e:
        语句组2

        执行语句组1。如果执行过程中没有产生异常,则不会执行语句组2。如果产生异常,程序并不会中止,而是立即从语句组1中跳出,去执行语句组2。例如:

try:
    n = int(input())
    print("hello")
    a = 100/n
    print(a)
except Exception as e:
    print(e)    #输出导致异常的原因的信息,不是必需的
    print("error")
print("end")

        程序执行结果可能如以下几种情况:

5↙
hello
20.0
end

        输入5,没有异常发生,因此第7、8行不会执行。

0↙
hello
division by zero
error
end

        输入0,在第4行除数为0导致异常,第5行不执行,跳到第7行继续执行。

        “division by zero”是第7行输出的导致异常的原因。

abc↙
invalid literal for int() with base 10: 'abc'
error
end

        输入abc,在第2行试图将字符串'abc'转换成整数的时候即发生异常,第3行到第5行都不会执行,程序跳至第7行继续执行。

        有的时候,希望对发生的异常强硬地不加理会,程序继续运行就好,那么可以这么写:

try:
        ……
except Exception as e:
        pass

        pass是Python语句,表示什么都不做,可以用在任何地方。用在任何地方都没什么作用,就是占个位子而已。

        另外,“except Exception as e:”也可以简写为“except:”。

        OpenJudge上的有些题目,没告诉你有多少数据,输入数据也没有结束的标志(有的题目会说输入一行“end”表示数据结束),这种情况下就需要用异常处理来进行输入。

3.6   调试程序的方法

        学到循环,程序就会略有一点复杂,出错概率大增,必须学会一些调试程序的方法。

        运行程序时,出现RuntimeError是很常见的。此时PyCharm会有出错信息,要仔细看,出错信息会指出程序在第几行出错。如果用到各种库,那么出错信息可能就会有很多,一些错误发生在并非自己编写的.py文件里。耐心往下看,出错信息里一定会指出自己写的.py文件到底哪一行出错。然后查词典也要看明白出错信息说的啥。

        导致RuntimeError的原因,通常是输入数据结束了还执行input()、列表下标越界、不合法的转换、数值和字符串相加等。1.12节有详细说明,请仔细阅读。

        如果程序可以运行,但就是得不到想要的结果,那就是存在逻辑错误。PyCharm提供了单步执行程序进行调试的功能,但是作者认为这么做效率不高,不推荐。推荐的做法是到处加print语句:用print语句输出你关心的变量的值,看看其变化过程是否正确;在if语句的每个分支都加print语句,就能看清楚到底哪个分支被执行;在循环里面加print语句,就能看到循环执行的次数到底对不对—总之,在各种地方都可以加print语句来看这个地方有没有被执行到。在这些用于调试的print语句后面不妨用注释做个标记,比如“#debug”,这样便于在正式版本里找到它们并删除。

        在OJ做题时,最烦恼的是在本机能通过样例数据,但是程序提交后却得到WrongAnswer。此时就要自己多做一些数据进行测试。对于多组数据的题目,测试的时候一定也要用多组数据,因为忘了在处理每组数据前初始化一些变量,是老手都容易犯的错误。做测试数据的时候,要特别注意特殊情况、边界情况,比如负数、0、1、长度为1的字符串,数据范围里的最大值、最小值等。若输入数据是整数,不要偷懒都用1位整数,应该用不同位数的整数;输入数据是字符串,就要用不等长的字符串—总之测试数据应该有多样性,覆盖尽可能多的情况。如果程序有多个分支,则应构造不同的测试数据,使得每个分支都执行到,不能有未经测试的分支。

        上面这些测试方法,不仅适用于做OJ题,真实的软件开发测试也要这么做。

        再次强调一点,在OJ做题,不要犯程序输出的大小写和题目要求不一致的错误。

        Python的assert语句也有助于发现程序bug,其用法如下:

assert 条件,提示

        如果条件满足,则assert语句什么都不做;如果条件不满足,assert语句会导致RuntimeError,出错信息里会包含提示。例如:

asserta != 0,"a等于0了,错!"

        假定变量a前面已经有定义,且a的值无论如何不该为0。如果a的值为0,程序可能出错,也可能运气好暂时不出明显的错(这样就发现不了a变成0了),但程序说不定有隐患—那么上面的语句就能确保a为0时,程序一定出错,从而就可以去找出a变成0的原因。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值