一、前言
上一章,我们大概了解了一下python中的所有数据类型,但作为一门编程语言,这还远远不够。
在1966
年,计算机科学家 Bohm
和 Jacopini
证明了这样的事实:任何简单或复杂的算法都可以由顺序结构、选择结构和循环结构这三种基本结构组合而成。
也就是说,想要真正能够编写程序,这三种基本结构是必不可少的。
这也就是本章的标题“控制流”,意为控制整个程序的运行流程。
二、顺序结构
顺序结构是最简单的,正如其名字的含义:顺序执行
而大部分编程语言,包括python
,默认就是顺序执行的,比如下面这段代码:
print("1111")
print("2222")
print("3333")
其执行顺序就是从上到下开始执行的,这可以从它的打印结果中看出来:
1111
2222
3333
三、选择结构
顺序结构的一大难点在于,无法进行选择执行,比如当一个数字大于0,我就打印它大于0,否则就打印它小于等于0。
如果使用顺序结构,除非修改代码,否则它必然会执行所有的代码:
a=10
print("a>0")
print("a<=0")
这时候就需要选择结构了,所谓选择,就是看情况来执行某一段代码,或者不执行某一段代码。
python中的选择结构如下所示:
a=10
if a>0:
print("a>0")
if a<=0:
print("a<=0")
如果a大于0,就打印a>0
,如果a小于等于0,就输出a<=0
。
用到的关键字为if
,意思就是“如果”。
在它的后面紧跟一个判断语句就行了,这和数学中的概念是一致的,应该不用多说。
只是需要注意一下大于等于、小于等于、不等于以及等于的写法:
a=10 #一个=为赋值的意思
a==10 #两个=才是判断是否等于
a<=10 #小于等于是用<与=两个符号组合的
a>=10 #大于等于是用>与=两个符号组合的
a!=10 #不等于是用!与=两个符号组合的
判断完成后,需要在其后面添加一个:
符号,代表后面跟着的语句就是当前面的判断语句为真时,要执行的语句。
注意这里的写法:
if a>0:
print("a>0")
需要当前面if
语句为真时才执行的语句,必须要在前面打上一个tab
键(一般一个tab
表示4个空格),也称缩进,python解释器就是通过缩进来识别语句所属块的。
比如像上面那样写,就代表后面的那个print
语句属于前面的if
语句,只有if
后面的判断为真,才会执行它
如果有多条语句,那么每条语句都要有相同的缩进:
a=10
if a==10:
print("1前面有缩进,属于上方的if语句块")
print("2前面有缩进,属于上方的if语句块")
print("3前面没有缩进,不属于上方的if语句块")
就我个人而言,并不太认可使用“缩进”的方式规范代码块,毕竟这样写,如果代码量一多,实际上并不利于观察,但这是python语言的语法规定,只能适应了。
其它语言一般采用的都是
{}
的方式,将属于自己的代码用大括号包起来,个人觉得观察起来更加方便。
但你会发现,一个数要么大于0,要么就小于等0,这种只存在两面性的条件,如果要用if
语句判断两次就太麻烦了。
所以我们可以通过else
关键字来代替其它情况:
a=10
if a>0:
print("a>0")
else:
print("a<=0")
注意else
不能单独出现,因为它的意思就是除此之外,即上面这段代码的意思就是:如果a大于0,则输出a>0
,否则,就输出a<=0
。
同时注意,else
关键字后面同样也是用的:
,然后属于它的代码也需要前面有缩进才行。
在只有正反两面的情况下,上面的语句可以很好的工作,可一旦出现了多种情况,就不行了。
比如现在我想要判断负数、0-10,以及大于10的数,这三种情况。
if else
只能判断两种情况的条件,一旦出现了多个,如果发现要用上面的if语句,你就得写三条if
语句
a=10
if a<0:
print("a<0")
if a>=0 and a<10:
print("a>=0 and a<10")
if a>=10:
print("a>=0")
注意第二条语句,由于要在0
和10
之间,所以需要判断两次,由于前后执行的结果都是布尔类型,所以就可以用到上一章提到的and
。
也就是只有前后两个条件都为True
,它的整个结果才为True
,进而才会执行这条if
后面的语句。
当然,由于python语言过于高级,你完全可以这样写:
if 0<= a <10:
print("a>=0 and a<10")
这就和数学里面的表示方法差不多了。
观察上面的这种形式,还是觉得有点不优雅,毕竟这三个条件是同一个变量上的三种划分,这样写成三条if
语句,就不容易看不出来三个条件的关联性了。
这个时候,我们就可以使用elif
语句了:
a=10
if a<0:
print("a<0")
elif 0<= a <10:
print("a>=0 and a<10")
else:
print("a>=10")
它的意义就在于,如果不满足第一个if
语句,那我就继续判断elif
后面的条件,如果还不满足,那才执行else
后面的代码。
elif
是else if
的缩写,同样也是个判断语句,后面紧跟判断条件与:
,以及要执行的代码块。
它与if
不同之处在于,它只能跟在if
后面,用来判断更多的条件。并且可以添加多个。
发现了没,如果你用三条
if
语句,那就无论如何都要判断三次,而如果采用if elif else
语句,只要前面某个条件满足了,后面的判断就不会执行了,进而就提升了程序的运行效率。
同时最后,还可以添加else
语句,用来判断其它情况。
比如下面这段代码:
a=10
if a<0:
print("a<0")
elif 0<= a <10:
print("a>=0 and a<10")
elif 10<=a<20:
print("a>=10 and a<20")
else:
print("a>=20")
应该能看懂上面的代码吧?
除了上面这一种选择结构外,自3.10版本之后,python还支持match
匹配模式进行选择,它更加强大,但鉴于其目前还处于早期,并且这是基础章节,就留到以后再讲了。
所以在python中,只要你需要进行判断的地方,选择if
语句就对了。
四、循环结构
循环结构的作用就在于,它可以重复执行一段固定、或者有规律的代码,进而提升我们码代码的效率。
比如现在我想要输出五个“hello world”
,如果没有循环语句,那我们就不得不写五次:
print("hello world")
print("hello world")
print("hello world")
print("hello world")
print("hello world")
虽然复制粘贴很容易,但程序中出现大量的重复代码,会使得维护成本大大提高。
比如,现在我不想要输出hello world
了,我想要输出hello python
,那你可能就不得不修改这五处地方才行。
还有如果我还想要每打印一次,同时还要其后面跟上它是第几句的话,那就更加麻烦了:
print("hello python1")
print("hello python2")
print("hello python3")
print("hello python4")
print("hello python5")
为了解决上面罗列的这些麻烦,就出现了循环结构。
python中一共只有两种循环:for
与while
我们首先来看比较简单的while
循环:
a=5
while a!=0:
print("hello python")
a=a-1
同样是输出五次相同的字符串,但这次我们却只需要写print
一次就行了!
上面这段代码,确实与上面介绍的if
有点像,while
后面跟着的同样是一个布尔表达式,只要这个表达式为True
,那就不断执行后面紧跟着的语句,同样的,它后面也是用:
来标识。
而属于它的代码片段,前面同样需要一个tab
(4个空格)来标注。
这段代码的执行逻辑是:
- 让a等于5
- 判断a是否等于0,如果不等于0,就执行属于它的代码块
- 如果不等于0,那就执行一次
print
和a减一
- 执行完成后,再返回判断现在a是否为0,如果仍然不为0,那就重复刚才的步骤,如果为0,那就执行结束,继续向下走执行其它语句。
- 由于这里没有其它语句,所以程序就执行结束了。
如果想要无限循环打印,知道怎么写吗?
while True:
print("hello python")
直接让布尔表达式恒等于True
即可,此时程序将永远不会执行结束,只能强制中断它,你可以按终端按快捷键Ctrl+C
实现强制终止程序执行。
循环语句非常的有用,比如我现在想要打印0-100
中的奇数,亲手写print将其打印出来显然有些不可能。
所以这时候就可以用循环语句:
a=0
while a<100:
if a%2==1:
print(a)
a=a+1
当然,这还需要结合前面提到的if
语句
注意:这里的
tab
的空格距离,因为它属于if
,所以需要比if
多一个tab
,但由于if
又属于while
中,if自己的前面就需要一个tab,所以综合下来它就是两个tab的距离,而后面的a=a+1
,由于它属于while
,而不属于if
,所以只有一个tab
的距离,如果不属于while
语句的,那其前面就没有tab
而%
是求余运算符,比如 10%2=5.....0
,所以结果为0
,11%2=5....1
,余数为1
,说明它就是奇数。
当然,除了上面的那种用法外,我们在循环中还有两个经常用到的关键字:break
与continue
break
就是停止循环,比如下面的代码:
a=0
while a<100:
if a%2==1:
print(a)
if a==50:
break
a=a+1
我在上面的循环中又添加了一个判断语句,如果a等于50
了,那我就跳出循环,也就是不继续在这里执行了。
效果就是,只输出0-50
的奇数,
相比于break
这种直接跳出循环的粗暴操作,continue
就要好一些,它只跳过当前的语句:
a=0
while a<100:
a=a+1
if a%2==0:
continue
print(a)
比如我将代码改写成为了上面这样。同样是输出0-100中的所有奇数。
但不同之处就在于,这里的判断语句是,如果它为偶数,那我就continue
,即跳过当前这次循环,不再执行后面的语句,然后直接来到下一次循环
代码的语义就从原来的:如果这个数是奇数,那我就打印它,变成为,如果这个数是偶数,那我就跳过它,否则,我才打印它。
这两个关键字在循环中是非常常见的,以后你也会经常看到。
除却while
循环外,使用频率更高的可能还是for
循环,比如上面的代码,用for
循环写的话,就会更加的简洁
for i in range(0,100):
if i%2==1:
print(i)
它主要有两个关键字:for
与in
简单来就是,for
后面的i
这个变量,要遍历in
后面的这个范围。
这里用到的python
中的range
函数产生的一个0到100的范围,用来给i
进行遍历。
后面章节聊到函数时,会再给大家详细讲解python中的一些常用函数以及作用
这样做,我们就无需每次都要判断是否大于0之类的事情,因为范围已经由in
后面的range
函数确定了。
最后同样是用:
进行分隔,属于它的代码,前面同样要有一个tab
键的空格。
至于里面的代码,与上面的一致,就不再讲解了。
这么看起来你可能觉得它也没什么特殊之处。所以下面我们来尝试遍历一个数组试一试:
arr=['111','2222','333','444','555']
i=0
while i<len(arr):
print(arr[i])
i=i+1
上面是用while
语句写的代码,用到了python
中的len
函数,它的作用就像它的名字,就是用来求取长度的,这里求取的就是这个数组的长度
最后通过变量i,对其进行遍历,可以发现非常麻烦,但如果用for
循环,就极其简单:
arr=['111','2222','333','444','555']
for i in arr:
print(i)
这里的i就是数组中的每个元素,直接就可以取出来,而不用像上面的while循环那样,还需要用一个数字,通过数组下标才能进行遍历出其内部的元素。