流程控制
大纲
- 前言
- 条件判断语句
- if语句
- elif语句
- else语句
- 嵌套的条件语句
- 用字典代替多个if/else
- 占位语句
- 循环语句
- for循环语句
- while循环语句
- 主动结束循环
- 跳过当前循环
- 鲜为人知的else尾巴
- 总结
前言
至今为止,我们做的程序都是顺序结构的,没有任何逻辑,只有一股脑地从上到下一句执行完又到下一句,下面我们来学习流程控制语句,以改变我们程序的执行顺序,让它变得更有趣些
条件判断语句
"如果能重来,我要选李白,否则我就继续当李荣浩。",这就是条件判断,它根据条件的不同,使程序走向不同的流程
if语句
在python或绝大多数编程语言中,用if表示如果,它的格式如下
if : if内语句1 if内语句2if外语句3
冒号后回车,再以4个空格缩进为代码块,以上语句1、2都在代码块内,但语句3不在if代码块内
如果条件成立(条件为布尔值True时),则先执行其代码块内的代码,否则将不执行
如果以代码的方式来表示李荣浩的那句歌词,大概长下面这个样子
# 能重来这个条件是成立的again = Trueif again: print('我要选李白') print('几百年前做的好坏 没那么多人猜') print('至少我还能写写诗来澎湃 逗逗女孩') print('创作也能到那么高端 被那么多人崇拜') print('继续唱')# 把能重来这个条件设为不成立again = Falseif again: print('我要选李白') print('几百年前做的好坏 没那么多人猜') print('至少我还能写写诗来澎湃 逗逗女孩') print('创作也能到那么高端 被那么多人崇拜') print('再继续唱')
结果如下
我要选李白几百年前做的好坏 没那么多人猜至少我还能写写诗来澎湃 逗逗女孩创作也能到那么高端 被那么多人崇拜继续唱再继续唱
可以看到当我们把条件设为不成立后,第二个if代码块内的代码并不会执行
事实上,在python中,if并不需要一定接收布尔值,如果接受的是非布尔值,解释器会自动将它转为布尔值,例如
a = '条件'# 以字符串a作为条件if a: print('条件成立!')
虽然字符串"条件"并不是布尔值,但是解释器会把它自动转为布尔值,您可以通过内置函数bool把一个非布尔值的类型主动转为布尔值
is_ok = bool('条件')print(is_ok) # Trueprint(type(is_ok)) #
在python中,空值 None 、整数 0 、空字符串 "" 、空列表 [] 、空元组 tuple() 、空字典 {} 和空集合 set(),它们被转化为布尔值时,皆被认为是False,其余都为True
# 空值Noneprint(bool(None)) # False# 整数0print(bool(0)) # False# 空字符串print(bool('')) # False# 空列表print(bool([])) # False# 空元组print(bool(tuple())) # False# 空字典print(bool({})) # False# 空集合print(bool(set())) # False
在条件语句中有如下常用的操作运算符,它们的结果类型都是布尔值
操作符作用例子结果==比较左右两者是否相等1==1True!=比较左右两者是否不相等1!=2True>比较左边值是否大于右边值2>3False小于右边值3<2False>=比较左边值是否大于或等于右边值3>=3True<=比较左边值是否小于或等于右边值2<=3Truenot表示对值进行取反,将True变为False 或 将False变为Truenot 1False
还有两个操作符,但它们的结果类型取决于操作数的类型
操作符作用例子结果and顺序查看左右两者的布尔值是否为True,直到遇到False或最后一个时即退出,并返回退出时的值0 and 1或1 and 0皆为0or顺序查看左右两者的布尔值是否为True,直到遇到True或最后一个时即退出,并返回退出时的值0 or 1或1 or 0皆为1
可以通过以下例子来加深理解
# and的例子a = 1 and 'hello' # 先看1的布尔值为True,继续看'hello'的布尔值也为True,到达最后一个,退出,所以a='hello'b = 0 and 'no' # 先看0的布尔值为False,退出,所以b=0c = {1} and [] # 先看非空集合的布尔值为True,继续看空列表的布尔值为False,退出,所以c=[]# or的例子d = 0 or '' # 先看0的布尔值为False,继续看空字符串的布尔值也为False,到达最后一个,退出,所以d=''e = [1] or (1,) # 先看非空列表的布尔值为True,退出,所以e=[1]f = tuple() or 2 # 先看空元组的布尔值为False,继续看2的布尔值为True,退出,所以f=2# 结合if来使用number = 6print(6 > 5) # 6大于5,Trueprint(6 < 10) # 6小于10,True# if的条件相当于True and True,所以条件当然成立了if 6 > 5 and 6 < 10: print('6比5大,但比10小')
elif语句
elif是else if的简写,它可以与if组成多条件判断,它表示再如果,elif不能脱离if单独使用,格式如下
if 条件1: 语句1 语句2elif 条件2: 语句3 语句4elif 条件3: 语句5 语句6
例如做一个根据考试分数来评价是否优秀的示例程序
# 判断成绩# 85分以上为优秀# 60~85分为中等# 60以下为不及格# 分数为61score = 61if score >= 85: print('优秀')elif 60 <= score < 85: print('中等') # 打印出这一句elif score < 60: print('不及格')
60 <= score < 85这一句,它等价于(60 <= score) and (score < 85),这里小括号加与不加效果都一样,因为是比较运算符先结合,再轮到and操作符
注意条件判断是顺序判断的,如果某个条件成立了,无论其后条件成立与否,都不会去执行了,例如
score = 61if score > 60: print('中等') # 打印出这句后,退出条件判断elif score >= 85: print('优秀')print('结束') # 结束
所以顺序很重要
else语句
else 表示 否则,当所有的if或elif的条件都不成立时,将会执行else内的代码块
else也不能脱离if单独使用,但与elif不同,它还可以与另外两个语句搭配使用,后面将会介绍到
所以条件判断语句的完整格式如下:
if 条件1: 语句1 语句2elif 条件2: 语句3 语句4else: 语句5 语句6
当条件1和2都不成立时,else内的语句5、6将会被执行
利用else,我们可以将分数判断程序改写成
score = 99if score >= 85: print('优秀') # 打印出这一句elif score >= 60: print('中等')else: print('不及格')
是不是更加的简洁了?
注意不能把score >= 60放在第一个条件中,否则分数99永远只会打印出中等
我们可以利用内置函数input来让用户自己输入分数,在此之前要注意input获取到的值类型是字符串,所以得先把字符串转为数字
可以用内置函数int将字符串转为整数,或用内置函数float将字符串转为浮点数,前提是所输入的字符串必须可以被转化为数字,否则将会报错
number = input('输入一个数字:') # 输入8后回车print(number) # 8print(type(number)) # # 利用内置函数int将它转为整数int_number = int(number)print(int_number) # 8print(type(int_number)) # # 利用内置函数float将它转为浮点数float_number = float(number)print(float_number) # 8.0print(type(float_number)) #
利用input函数,分数判断程序可以改写成这样
score = input('请输入您的分数:')score = float(score)if score >= 85: print('优秀')elif score >= 60: print('中等')else: print('不及格')
嵌套的条件语句
您可以将if...elif...else条件语句嵌套到另外一个if...elif...else中
注意4个空格表示一个代码块,相同缩进数的语句在一起组成一个语句块
格式大概长下面这样
if 条件1: 语句 if 条件2: 语句 elif 条件3: 语句 else: 语句elif 条件4: 语句else: 语句
利用嵌套条件语句,我们让分数的划分更细一点
score = float(input('请输入您的分数:'))if score >= 85: if score >= 95: print('极优秀') else: print('优秀')elif score >= 60: if score >= 80: print('良好') elif score >= 70: print('中等') else: print('及格')else: print('不及格')
可以通过Python Tutor代码执行可视化网站 http://pythontutor.com/visualize.html,来看到程序的每一步执行情况
例如输入分数为75
用字典代替多个if/else
试想有以下代码,根据数字1~7来判断今天是星期几
num = int(input('请输入数字1~7:'))if num == 1: day = '星期一'elif num == 2: day = '星期二'elif num == 3: day = '星期三'elif num == 4: day = '星期四'elif num == 5: day = '星期五'elif num == 6: day = '星期六'elif num == 7: day = '星期天'else: day = '未知'print(day)
如何来让它变得更简洁些呢?
在某些编程语言中,可以利用switch...case来简化,但是python并没有switch语句,但是我们可以利用字典键值对的特性来达到同样的目的
num = int(input('请输入数字1~7:'))day_dict = {1:'星期一', 2:'星期二', 3:'星期三', 4:'星期四', 5:'星期五', 6:'星期六', 7:'星期天'}print(day_dict[num])
貌似简洁多了
但是有个问题,如果用户输入的不是1~7数字,将会报错,上面的代码并没有做到else的效果
可以巧妙利用字典的get方法来达到else的效果,它的格式像这样dict.get(self, key, default=None, /)
a = {'a':1, 'b':2}# 下面这行将会报错# print(a['c'])# 利用字典get方法来获取键'b'的值print(a.get('b')) # 2# 但当不存在键时,会返回空值Noneprint(a.get('c')) # None# 可以为get方法添加一个默认值print(a.get('c', '没有哦')) # 没有哦
所以我们可以把最后一行代码改成print(day_dict.get(num, '未知')),效果就一模一样了
占位语句
因为python以缩进为代码块的特性,python有一个其他编程语言都没有的语句,它叫做占位语句
占位语句用pass标识,它表示通过的意思,就是告诉python解释器,我在这里占着茅坑不拉屎,你不用管我,继续往下走
假如您的if语句的内代码块啥也不做,或者暂时还没想好要做些啥,pass就派上用场了
num = 10if num > 5: # 我还没想好大于5时,if内代码块要做些啥 # 先来个pass语句占着位置吧 # 因为如果不占个位,就会报语法错误 passelse: print('小于或等于5哦')
循环语句
请用python算出1+2+3的和
>>> 1+2+36
so easy
请再用python算出1+2+3.......+10的和
>>> 1+2+3+4+5+6+7+8+9+1055
请再用python算出1+2+3.......10000的和
所以这时候,循环就派上用场了!
在python中,有两种循环,它们分别是for循环与while循环
for循环语句
for循环的格式是for 变量名 in 可迭代对象
在python的基本数据类型中,字符串str、列表list、元组tuple、集合set、字典dict这5个皆为可迭代类型(对象),也就是说,我们可以通过for...in循环来遍历其内成员(元素)
# 遍历字符串for s in 'abc': # 字符串内的每一个字符'a'、'b'、'c'都会依次赋值给变量s print(s)# 遍历列表for i in [1,2,3]: # 列表内的成员1、2、3会依次赋值给变量i print(i) # 遍历元组、集合的效果和遍历列表基本一致,就不举例了pass# 与其它基本数据类型不一样,遍历字典时,会把字典的键赋值给变量,而不是字典的值d = {'a':1, 'b':2}for k in d: print(k) # 依次打印a与b print(d[k]) # 通过键获取对应的值# 可以通过字典的values方法,直接遍历字典的值for v in d.values(): print(v) # 依次打印1、2 # 可以通过字典的keys方法,遍历字典的键,这里与直接遍历字典的效果是一样的for k in d.keys(): print(k) # 依次打印a与b # 可以通过字典的items方法,同时遍历字典的键与值for k, v in d.items(): print(k,v) # 先打印a与1,再打印b与2
这里您可能不理解items那一段是什么鬼,这里涉及到python变量解包的知识
# 在一章中,我们学过多个变量的赋值a, b = 1, 2print(a, b) # 1 2# ok, 没问题# 在那一章中,我们知道1,2这样会被python解释器当作是元组c = 1, 2print(c) # (1, 2)print(type(c)) # # 所以一开始的a,b=1,2等价于a, b = cprint(a, b) # 1 2
这就叫变量解包,我们知道了多个变量赋值的真相!
通过内置函数list,我们可以将可迭代对象转化为列表
d = {'a':1, 'b':2}e = list(d.items())print(e) # [('a', 1), ('b', 2)]# 看到了吗# 一个列表里,每个元素都是一个长度为2的元组# 这样试试for both in e: print(both) # 先打印('a', 1),再打印('b', 2)# 加上我们的变量解包呢?for key, value in e: print(key,value) # ok,现在明白了
for循环的基友range
内置函数range是for循环的好基友,range是Range Rover(路虎)的range,它中文意思是一段范围,我们可能暂时玩不起Range Rover,但是我们必须得把range给玩溜了,才能玩好for循环
range函数有两种格式,它们都返回一个可迭代对象
range(stop) -> range objectrange(start, stop[, step]) -> range object
直接上例子
# 只给一个参数,表示结束位置(不包含),它表示[0~结束位置)这段范围print(list(range(3))) # [0, 1, 2]# 传入两个参数,第一个参数表示起始位置(包含),第二个参数表示结束位置(不包含),它表示[起始位置~结束位置]这段范围print(list(range(1, 6)) # [1, 2, 3, 4, 5]# 传入三个参数,第一、二个参数和上面一样,第三个表示步长,即每次跨多少步# 当传入两个参数时,步长默认为1# 下面表示范围从[1~10],步长为2,所以得到了1到10内所有奇数组成的列表print(list(range(1, 10, 2))) # [1, 3, 5, 7, 9]# 与for循环配合for i in range(3): print(i) # 依次打印1~3
所以1+2+3.......10000的和,我们可以通过for与range的配合求出
# 一开始将总数设为0sum = 0for num in range(1, 10001): # 将1~10000的每个数累加到sum上 sum = sum + numprint(sum) # 50005000
解放双手,美滋滋!
我们再通过观察for循环的每一步走向来更深一步了解它
for循环的又一基友enumerate
内置函数enumerate作用于可迭代对象,比如利用它,可以同时遍历列表的数据和数据的下标(索引)
函数的格式长这样
enumerate(iterable, start=0)
直接上例子
a = ['a', 'b', 'c']for index, data in enumerate(a): print(index, data) # 顺序打印 # 0 a # 1 b # 2 c
将列表传给函数enumerate后,它的返回值和字典的items方法返回值有点像
a = ['a', 'b', 'c']b = enumerate(a)# 利用内置函数list将可迭代对象转为列表看看print(list(b)) # [(0, 'a'), (1, 'b'), (2, 'c')]
将enumerate的返回值转成列表后,可以看出,这是所有元素都是长度为2元组的列表,其中,元组第一个值为列表元素的下标,第二个值为对应的元素
while循环语句
第二种循环叫做while,它的格式长下面这样
while 条件: 语句1 ... 语句N
当条件满足时,将不断循环执行代码块内容,直至条件不满足时正常退出循环
比如同样计算1+2+3.......10000的和,用while循环的话,可以这样
sum = 0num = 1while num <= 10000: sum = sum + num num = num + 1print(sum) # 50005000
通过动画来看流程是这样的
主动结束循环
至今为止,无论是for循环还是while循环,它的结束都是正常结束的,要么可迭代对象已迭代完毕退出,要么条件不满足退出
我们可以通过break语句来主动退出循环
当while的条件为真时,将进行下一次循环,如果while的条件永远是True的话,就变成了死循环,像下面一样
while True: print('你好帅啊')
如果您有耐心,机器将会日夜不停地赞美您,如果您感到厌烦,可以通过按键Ctrl+C来终止它
利用break语句,当赞美了两次后,主动退出循环
times = 0while True: if times == 2: # 当times变量等于2时,break退出循环 break print('你好帅啊') times = times + 1print('谢谢,但是地球人都知道')
跳过当前循环
跳过当前用continue语句,它表示继续的意思,当在循环中遇到continue后,其后的语句不会执行,而是继续下一次循环
例如,当数字等于2时,不进行打印
for i in range(1, 4): if i == 2: # 遇到continue后,其后的语句不会执行,而是继续下一次循环 continue print(i)
通过动画来看流程是这样的
鲜为人知的else尾巴
话说"花心"的else不但可以与if条件语句进行搭配,它还可以与循环进行搭配,所以我们揭开了两种循环的面纱,看到了它们的最终面貌
for循环
for in : else:
while循环
while : else:
else下的代码块只会在循环正常退出时执行,所谓正常退出,是指非break主动退出循环的情况下,循环正常结束退出
我们在循环中通过动画看两种循环结束情况的执行逻辑
- 正常结束循环
- break主动结束循环
总结
熟练掌握条件判断语句与循环语句,将让您的程序更有逻辑性