Ⅲ 程序流程控制
程序流程控制(一)
python 是通过一些程序结构来控制程序的执行顺序和流程的。
1⃣️ 程序结构
计算机程序是一条条按顺序执行的指令。顺序结构是计算机程序的基础,但单一的顺序结构不能解决所有问题。计算机程序由三种基本结构组成:
-
顺序结构
-
分支结构
-
循环结构
1. 顺序结构
我们每天早上起床,穿衣服,洗脸,刷牙,叠被子,吃早餐,这些按照单一顺序进行的就是顺序结构。
顺序结构是程序执行的基本流程,它会按照代码从上往下的顺序依次执行。
a = 1
a += 1
print(a)
2
例如上面的代码,执行流程为
-
定义变量
a
,并赋值为整数 1 -
变量
a
自加 1 -
调用函数
print
输出变量a
的值
从上往下依次执行
2. 分支结构
出门时是否带伞要根据天气条件进行判断,如果天气好就不带,如果可能下雨或正在下雨就要带,这就是分支结构。
分支结构是程序根据条件判断结果而选择不同代码向前执行的一种方式,也叫条件分支。
分支结构包括:
-
单分支
-
二分支
-
多分支
2.1 单分支
在 python 中单分支结构通过 if
语句来实现,语法如下:
if <条件>:
语句块
-
注意条件语句结束后要紧跟冒号
-
语句块是
if
条件满足后执行的一条或多条语句序列 -
语句块中语句通过缩进与
if
语句所在行形成包含关系 -
缩进按照规范为 4 个空格
if
语句会首先计算 <条件>
表达式,如果结果为 True
则会执行所包含的语句块,结果为 False
则会跳过所包含的语句块。
if
语句中的语句块的执行与否依赖于条件判断。但无论什么情况,控制都会 转到与 if 语句同级别的下一条语句。
案例:成绩是否及格
input 函数
input
函数用来接收用户输入的文本信息,然后以字符串的形式返回,它接收字符串参数作为提示信息输出。
⭐
一个程序,有开始,有结束 ->绝大多数情况下
代码的执行逻辑:从上到下,从里到外
score = input('请输入你的成绩>>>:')
print(score,type(score))
请输入你的成绩 >>>:100
100 <class 'str'>
score = input('请输入你的成绩>>>:')
# 转换类型
score = float(score)
# 判断
if score < 60:
print('没及格,赏一巴掌')
if score >= 60:
print('有进步,么么哒,亲一下')
请输入你的成绩 >>>:100
有进步,么么哒,亲一下
2.2 二分支
python 中二分支结构通过 if-else
语句来实现的,语法 格式如下:
if <条件>:
<语句块1>
else:
<语句块2>
-
< 语句块 1> 是在 if 条件满足后执行的一个或多个语句序列
-
< 语句块 2> 是 if 条件不满足后执行的语句序列
- if,else是关键字,条件和else后面的冒号不能省略
-
注意缩进,< 语句块 2> 通过缩进与 else 所在行形成包含关系
二分支语句用于区分 < 条件 > 的两种可能 True 或者 False,分别形成执行路径
案例:成绩是否及格(2)
通过二分支改进案例成绩是否及格
score = input('请输入你的成绩>>>:')
# 转换类型
score = float(score)
# 判断
if score < 60:
print('没及格,赏一巴掌')
else:
print('有进步,么么哒,亲一下')
请输入你的成绩 >>>:100
有进步,么么哒,亲一下
三目运算
二分支结构还有一种更简洁的表达方式,语法格式如下:
<表达式> if <条件> else <表达式2>
适合代码块为 1 行语句时,这种方式也叫三目运算。
上面的代码可以改写为:
score = input('请输入你的成绩>>>:')
# 转换类型
score = float(score)
# 判断
print('没及格,赏一巴掌') if score < 60 else print('有进步,么么哒,亲一下')
请输入你的成绩 >>>:100
有进步,么么哒,亲一下
对于简单判断,三目运算可以将多行语句写成一行,简洁明了。
2.3 多分支
python 通过 if - elif - else
表示多分支结构,语法如下:
if <条件1>:
<代码块1>
elif <条件2>:
<代码块2>
...
else:
<代码块3>
多分支是二分支的扩展,用于多个判断条件多条执行路径的情况。python 依次执行判断条件,寻找第一个结果为 True 的条件,执行该条件下的代码块,同时结束后跳过整个 if-elif-else
结构,执行后面的语句。如果没有任何条件成立,则执行 else 下的代码块,且 else 语句是可选的,也即是说可以没有 else 语句。
案例:成绩评价
上面的案例对成绩的评价太粗糙了,60 分就可以赏个么么哒。通过多分支改进上面的案例。
请根据用户输入的成绩,按一下等级分区:
-
< 40: E
-
40-60: D
-
60-75: C
-
75-85: B
-
85-100: A
score = input('请输入你的成绩>>>:')
# 转换类型
score = float(score)
# 判断
if score < 40:
print('等级:E')
elif 40<= score < 60:
print('等级:D')
elif 60<= score < 75:
print('等级:C')
elif 75<= score < 85:
print('等级:B')
else:
print('等级:A')
# 多分枝,尽量做到条件之间互斥
请输入你的成绩 >>>:100
等级:A
4 巢状分支
3. 循环结构
工作日每天 9:00 到公司上班,17:30 下班,周而复始,这就是循环结构。
python 中循环结构有两种:
-
条件循环也叫 while 循环
-
遍历循环也叫 for 循环
3.1 条件循环
python 中的条件循环通过 while
循环语句来实现,所以也叫 while
循环,语法格式如下:
while <条件>:
代码块
-
while
关键字空格后接条件表达式末尾加上冒号组成while
语句 -
代码块中的代码通过 4 个空格和
while
语句形成包含关系
while` 语句首先计算 `<条件>` 表达式,如果结果 `True`,则执行对应代码块中的语句,执行结束后再次执行 `<条件>表达式,再次判断结果,如果为 `True` 则循环执行,直到 `<条件>` 表达式为 `False` 时跳出循环,执行和 `while` 语句相同缩进的下一条语句。
当 <条件>
表达式恒为 True
时,形成无限循环,也叫死循环,需要小心使用。
当 <条件>
表达式恒为 Flase
时,则无法进入循环体
# 依次打印0-9
i = 0
while i < 10:
print(i)
i = i + 1
0
1
2
3
4
5
6
7
8
9
# 序列的循环
# 列表的元素循环
ls = ['a','b','c','d','e','f']
index = 0
while index < len(ls):
print(ls[index])
index += 1
a
b
c
d
e
f
# 散列的循环
# 集合没办法循环
dc = {'name': 'felix', 'age': 18}
index = 0
# 转换成列表
keys = list(dc.keys())
while index < len(keys):
print(dc[keys[index]])
index += 1
felix
18
⭐信息
⭐调试
3.2 遍历循环
python 中使用关键字 for
来实现遍历循环,也叫 for
循环,也叫迭代循环,语法格式如下:
for <循环变量> in <遍历结构>:
代码块
-
关键字
for
+ 空格 +<循环变量>
+ 关键字in
+< 遍历结构 >+ 冒号组成 for 语句 -
代码块通过缩进和 for 语句形成包含关系
for 循环会依次取出遍历结构中的元素,然后赋值给循环变量,每次遍历都会执行代码块,直到取出遍历结构中的所有元素。
所有可迭代对象都可以作为遍历结构进行 for 循环。
基本数据类型中序列数据类型,散列数据类型都可以进行迭代。
# for循环来遍历可迭代对象非常方便
# 序列的迭代
# 列表的迭代
ls = [0,1,2,3,4,5,6,7,8,9]
for i in ls:
print(i)
0
1
2
3
4
5
6
7
8
9
# 散列的迭代
st = {1,2,3,4,5,6}
for i in st:
print(i)
1
2
3
4
5
6
dc = {'name': 'xinlan', 'age': 18}
# 字典key的迭代
for key in dc:
print(key)
name
age
# 字典值的迭代
for key in dc:
print(dc[key])
xinlan
18
for value in dc.values():
print(value)
xinlan
18
迭代器(iterator)
迭代器是一个可以记住遍历位置的对象。for 循环迭代本质上就是通过迭代器来实现的。
通过内建函数 iter
可以创建迭代器。
iter('abc')
<str_iterator at 0x7fdc6a017670>
不是所有的数据类型都可以创建迭代器,凡是能够创建迭代器的对象称为 可迭代对象
,反之是 不可迭代对象
range 函数
# 场景:循环100次
for i in range(1,101):
print('打印第{}遍helle python'.format(i))
内建函数 range
,是序列类型数据,可以创建输出整数序列的迭代器。支持索引取值和切片操作。
range(start, stop,step)
range(i,j)生成 i,i+1,i+2,...,j-1
,start 默认为 0,当给定 step 时,它指定增长步长。
# 输出0-9
for i in range(10):
print(i)
0
1
2
3
4
5
6
7
8
9
# 输出1-10
for i in range(1,11):
print(i)
1
2
3
4
5
6
7
8
9
10
# 输出-1--10
for i in range(-1,-11,-1):
print(i)
-1
-2
-3
-4
-5
-6
-7
-8
-9
-10
for 循环经常和 range
函数配合用来指定循环次数。
⭐可以通过list()函数转化为列表类型的数据
print(list(range(10)))
print(list(range(1,5)))
print(list(range(1,10,2)))
⭐for 循环中的range -- 是迭代器,用于生成一个整数的序列
r = range(10) # 根据给到的一个数字,生成一个列表 -- 是可迭代的对象
print(list(r))
3.3 循环控制关键字
循环有时候需要主动中断来提高程序执行效率。
ls = [60,59,78,80,56,55]
# ls中存放的是所有学生的成绩
# 要判断是否有同学不及格
for i in ls:
if i < 60:
print('有同学不及格')
有同学不及格
有同学不及格
有同学不及格
可以发现上面的案例中,其实第二个成绩就不及格了,但是程序继续循环下去,如果数据量小,效率差别不大,但数据量大时会影响程序的执行效率。在实际的代码编写中会有很多这种情况,这是就需要能够主动结束循环的能力。
break
关键字
python 中循环结构可以使用 break
跳出当前循环体,脱离该循环后代码继续执行。
for i in ls:
if i >= 60:
print('有同学及格')
break
有同学及格
index = 0
while index < len(ls):
if ls[index] >= 60:
print('有同学及格')
break
有同学及格
for i in range(1,4):
for j in range(1,4):
if i==2:
break
print(i,j)
1 1
1 2
1 3
3 1
3 2
3 3
continue
关键字
python 中循环结构还可以使用 continue
关键字用来跳出当次循环,继续执行下一次循环。
# 输出所有奇数
for i in range(10):
if i%2 == 0:
continue
print(i)
1
3
5
7
9
for i in range(10):
if i%2 == 0:
break
print(i)
⭐continue 终止本轮循环,回到开头继续判断(如果再次判断,条件为False,就停止循环)
while a:
a -= 1
if a%2 == 0:
print("当前a的值为是偶是:{}".format(a))
continue # 4走的这个if,遇到continue会重新判断不会管后面的代码
if a<5:
print("a的值小于5,当前a为:{}".format(a)) # 所以最后a的值是3
break
print("循环结束了!")
else
关键字
循环结构还可以通过和 else
关键字进行配合,用来检测循环是否正常循环结束,还是 break
掉了。
for i in range(10):
if i%2 != 0:
continue
print(i)
else:
print('循环正常结束')
0
2
4
6
8
循环正常结束
for i in range(10):
if i%2 != 0:
break
print(i)
else:
print('循环正常结束')
0
"""
break:终止循环,(跳出循环体,执行循环之外的代码)
continue:中止当前本轮循环,直接进入下一轮循环,
break,continue:while和for 都适用。
"""
3.4 多层循环
print('* ',end=''): 输出时加参数 end='',让下一次执行print输出不换行
⭐第一层循环控制行,第二层循环控制列
打印正方形: n*n
打印三角形:
n = 9
for i in range(n):
for j in range(i+1):
print("* ",end='')
print()
打印乘法口诀表:格式化输出,左对齐,长度占四个字符
for i in range(1,10):
for j in range(1,i+1):
print("{}*{}={:<4}".format(j,i,i*j),end='')
print()
练习:
1.大小写互换,转换为镜像
2.输入一个年份,输出是否为闰年。
闰年条件:能被4整除但不能被100整除,或者能被400整除的年份都是闰年
year = int(input("请输入年份:"))
if year%4 == 0 and year %100 !=0 or year%400 == 0:
print("{}年是闰年".format(year))
else:
print("{}年不是闰年".format(year))
3.完成一个猜数字游戏
# 进入程序后
# 提示用户输入 要猜的数字
# 其他人输入时,提示数字大了,或者小了
# 猜到正确的数字为止,提示恭喜猜对了
# (选做:可以控制每位玩家的猜数字次数,例如,一个人只能猜3次,3次猜错结束程序,显示正确的数字后,重新开始)
# (选做: 猜数字的游戏中的数字尝试让系统生成,提示:random.randint(n,m) 可以让python在n-m之间生成一个随机数)
flag = 1
z = random.randint(1, 100)
m = 3
while flag:
n = int(input("请输入你要猜的数字:"))
if n > z:
print("大了")
elif n<z:
print("小了")
else:
print("恭喜猜对了")
flag = 0
m -= 1
if m == 0:
break
print("退出系统。。。")
4.一个5位数,判断它是不是回文数
# 个位与万位相同,十位与千位相同
# 方法一
num = input("请输入任意数:")
if num == num[::-1]:
print("是回文数")
else:
print("不是回文数")
/**
* num / 10000; //万位
*(num % 10000) / 1000; //千位
*(num % 1000) / 100; //百位
*(num % 100) / 10; //十位
* num % 10; //个位
*/
# 方法二
num = int(input("请输入任意五位数数:"))
if ((num//10000)==(num%10) and ((num%10000)//1000)==((num%100)//10) and num>=10000 and num<=99999):
print("%d是回文数"%num)
else:
print("%d不是回文数"%num)
# 方法三
x = int(input("请输入任意五位数数:"))
if __name__ == '__main__':
if x < 10000 or x > 99999:
print("输入错误")
else:
ten_thousand = x // 10000 #拆分最高位万位
thousand = x % 10000 // 1000 # 拆分千位
ten = x % 100 // 10 # 拆分十位
indiv = x % 10 # 拆分个位
if indiv == ten_thousand and ten == thousand:
print("%d是回文数" %x)
else:
print("%d不是回文数" %x)
# 方法四:http://c.biancheng.net/view/9816.html
5.使用代码完成一下逻辑,根据输入的行数打印如下图案
请输入需要打印的行数:5
*
***
*****
*******
*********
n = int(input("请输入需要打印的行数:"))
for i in range(1,n+1):
for j in range(1,n-i+1):
print(" ",end="")
for k in range(1,2*i):
print("*",end="")
print()
# 断点调试看
# 输入直角三角形,就先打印* 再打印空格
6.有1,2,3,4这四个数字,能组成多少个互不相同且无重复数字的三个数?分别是什么?
提示:123,321就是符合要求,数字既不相同,而且每个数字的个十百位也不重复;而121,212就不行,因为数字的各位与百位重复
lst = [1, 2, 3, 4]
lt = []
for a in lst: # 百位
for b in lst: # 十位
for c in lst: # 个位
if a!=b and a!=c and b!=c: # 每一位都不相等
num = a*100+b*10+c*1
lt.append(num)
print("符合要求的数共有{}个,分别为:{}".format(format(len(lt)),lt))
7.请用嵌套for循环输出如下等边三角形(三个边均是5个*)
@@@@@@*
@@@@@* *
@@@@* * *
@@@* * * *
@@* * * * *
for i in range(5):
for j in range(6-i):
print("@",end="")
for k in range(i+1):
print("*",end="")
print()
2⃣️ 异常处理
在程序的编写过程中会出现各种错误,语法错误在程序启动时就会检测出来,它是程序正常运行的前提条件。程序中还有一种错误发生在程序运行后,可能是由于逻辑问题,又或者是业务发生了改变,为了能让用户有更好的体验,加强代码的健壮性,我们需要对这些错误进行处理,也叫异常处理。
⭐异常:导致程序无法继续执行,例如:字符串和数字相加,除以0,对None进行操作
⭐中断当前程序执行,然后打印红字
1.异常处理
1.1 try-except
在 python 中通过 try-except
语句进行异常处理。
回忆我们前面关于成绩评价的案例,当用户输入非数值时程序会发生什么?
score = input('请输入你的成绩>>>:')
# 转换类型
score = float(score)
# 判断
if score < 40:
print('等级:E')
elif 40<= score < 60:
print('等级:D')
elif 60<= score < 75:
print('等级:C')
elif 75<= score < 85:
print('等级:B')
else:
print('等级:A')
请输入你的成绩 >>>:abc
ValueError Traceback (most recent call last)
in
1 score = input('请输入你的成绩 >>>:')
2 # 转换类型
----> 3 score = float(score)
4 # 判断
5 if score < 40:
ValueError: could not convert string to float: 'abc'
try-except
语句的基本语法格式如下:
try:
<语句块1>
except <异常类型1>:
<语句块2>
except <异常类型2>:
<语句块3>
语句块 1 中的代码如果发生异常,且异常与类型与对应 excep 语句中的异常类型相同则会被其捕获,从而执行对应的语句块
⭐当语句块1有多个不同类型的错误时,需要对不同类型的错误进行处理,要写多个except;不然会让没有异常的语句因为下面的错误语句也被独个的except进行处理。
try:
score = input('请输入你的成绩>>>:')
# 转换类型
score = float(score)
# 判断
if score < 40:
print('等级:E')
elif 40<= score < 60:
print('等级:D')
elif 60<= score < 75:
print('等级:C')
elif 75<= score < 85:
print('等级:B')
else:
print('等级:A')
except ValueError as e:
print(e)
print('请输入正确的成绩')
请输入你的成绩 >>>:aaa
could not convert string to float: 'aaa'
请输入正确的成绩
1.1.1)万能异常处理
1.1.2)单分支&多分枝
1.2 try-except-else
1.3 try-except-finally
1.4 try-except-else-finally
除了 try
和 except
关键字外,异常语句还可以与 else
和 finally
关键字配合使用,语法格式如下:
try:
<语句块1>
except <异常类型>:
<语句块2>
...
else:
<语句块3>
finally:
<语句块4>
代码执行流程如下:
没有发生异常时,会执行 else
语句后的代码块,不管有没有发生异常,finally
语句后的代码块一定会执行
try:
a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
index = input('请输入一个正整数>>>:')
index = int(index)
print(a[index])
except Exception as e:
print(e)
print('请输入一个正整数')
else:
print('没有发生异常')
finally:
print('我一定会执行')
请输入一个正整数 >>>:1
B
没有发生异常
我一定会执行
⭐
2. 异常种类:
指定异常类型:
找到异常后,直接执行处理,后面的异常不会捕捉(如分支条件的if/else):
如果有多个异常,其中一个没捕获到异常,报错:
3. 获取异常信息
⭐
断言:assert +表达式 (表达式返回一个bool值)
我希望是一个什么结果(预期结果) -- 常用元素定位,assert 标签是否存在
如果表达式是False,就会出现异常
练习
1.编写程序,键盘输入x和y的值,计算并输出表达式 ln(3x-1)/y的值。要求设置异常处理,对除0、负数求对数两种情况进行异常捕捉处理(math.log)
import math
while True:
try:
x = int(input("请输入x的值:"))
y = int(input("请输入y的值:"))
a = math.log(3 * x - 1) / y
print(a)
except ZeroDivisionError:
print("除数不能为0")
except ValueError:
print("发生异常,函数域U错误")
else:
break
2.定义input_password函数,提示用户输入密码.如果用户输入长度<8,抛出异常,如果用户输入长度>=8,返回输入的密码
3.写⼀个⽅法sanjiao(a, b, c),判断三个参数是否能构成⼀个三⾓形,如果不能则抛出异常Exception,
显⽰异常信息a,b,c”不能构成三⾓形”,如果可以构成则显⽰三⾓形三个边长,在⽅法中得到命令⾏输⼊的三个整数,调⽤此⽅法,并捕获异常
def sanjiao(a,b,c):
if a+b>c and a+c>b and b+c>a:
print(a,b,c)
else:
raise Exception("不能构成三角形")
sanjiao(3,4,5)
sanjiao(3,9,1)
4.从命令行得到5个整数,放入列表中,然后打印输出,要求:
如果输入数据不为整数,要捕获产生的异常,显示“请输入整数”
捕获输入参数不足5个的异常(越界),显示“请输入最少5个整数”
def option_ls():
list_1 = []
for i in range(5):
try:
j = int(input("请输入整数:"))
except:
print("请输入整数!")
else:
list_1.append(j)
if len(list_1) !=5:
raise Exception("请输入至少五个整数!")
option_ls()
5.编写代码调用CCircle方法,计算圆面积,定义一个异常,如果半径为 抛出异常
class RadioError(Exception):
def __init__(self,msg):
super().__init__(msg)
self.msg = msg
import math
def round():
try:
a = int(input("请输入半径:"))
if a<0:
raise RadioError("半径必须大于0")
else:
print(a**2*math.pi)
except RadioError as e:
print(RadioError,e)
except ValueError:
print("请输入数字类型")
round()