承接条件控制语句。条件控制语句像大树一样有很多的之差,那条路径通(也就是表达式判断为True)就会往哪一个树杈去运行,万涓溪水汇成大河。对于常用的程序结构形式,还有一种这篇文章就会讲解,那就是循环控制语句。正如前面所说,程序的执行是由上而下,从左至右的运行方式,但是如果我们遇到一件事情:需要做的事情都相似,只是需要重复做很多遍,如果只有条件控制语句,一个小细节就要执行一遍,那就太蛋疼了,因此除了在实际工作中遇到像大树一样逻辑的思路,我们需要让程序这种由上而下,从左只有的运行过程中,执行到我们想要重复做很多遍的事情,让这种法则局部“失效”。来回去运行计算,然后运行计算完毕后,继续按照这种运行法则向下去执行,答案是肯定的:那就是循环语句。
循环控制语句简介
我们把循环控制语句比作一个圆圈,符合一个条件就循环一次,符合一个条件就循环一次。和条件控制语句一样,其循环控制语句也有一个原则,这个原则叫避免死循环。
死循环:
也就是说,在一个循环体内,由于设置的表达语句一致符合某个条件,这样就跳不出这个圆圈而在里面一致执行(如果电脑不死机,一直执行到海枯石烂!)。所以切记在循环控制语句内一定要避免死循环的发生。
循环控制语句在python中有两种形式一种叫while循环控制语句,另外一种叫for循环控制语句。while看起来逻辑上比较繁琐,但是不能这样说,各自在解决某些问题上,都有相对好的选择。
第一部分: while 循环控制语句
存在形式如下:
(1) num = 0 # 计数器初始化
while num <=/< 表达式:
循环内容
num += 1 # 计数器运行部分# while循环语句要加一个计数器
(1) num = 0 # 计数器初始化
while num <=/< 表达式:
循环内容
num += 1 # 计数器运行部分
else: # 循环结束时执行这个位置
语句
解释如下:
其实这两种形式的区别就是后面增加了一个else:也就说形式(2) 整个循环体结束完毕后,再执行一个else:语句的内容。直白点儿说就是:“循环计算完毕,你还有什么话要说”?
因此,单独解释一下形式(1)即可:
计数器起到的作用就给定计数器一个初始值(这个变量名随便)随着表达式的内容一直为真,循环一直执行,每执行一次计数器累计一次,一直到累加表示部分为False了,整个循环体也就结束了。
详细逻辑:当程序执行到while语句时,首先要计算表达式的值,如果表达式的值为假,那么结束整个while语句。如果表达式的值为真,则执行语句,执行完成语句再去结算表达式的值;如果表达式的值为假,结束整个while语句,如此循环往复,直到表达式的值为假才停止。对于此,举几个例子。
举例1:循环计算列出1到5这几个数
1 # 举例1 2 num = 1 3 while num <= 5: 4 print(num, end="") 5 num += 1 6 # 输出结果:12345
举例2:循环计算1到100累计值
1 # 举例2 2 # 计算1-100的累加求和 3 sum = 0 # 初始化存放容器 4 num1 = 1 # 初始化计数器 5 while num1 <= 100: 6 sum += num1 7 num1 += 1 8 # print(sum) 9 print(sum) 10 # 输出结果:5050
举例3:循环把字符串中的每一个字符打印出来。
1 # 举例3 2 # 按顺序打印字符串中的每一个位置 3 str = "Thomas is a good man" 4 index = 0 # 计数器初始化 5 while index < len(str): 6 print("str[%d] = %s" % (index, str[index])) 7 index += 1 8 # 输出结果: 9 # str[0] = T 10 # str[1] = h 11 # str[2] = o 12 # str[3] = m 13 # str[4] = a 14 # str[5] = s 15 # str[6] = # 这里的空格也是字符串的一个字符 16 # str[7] = i 17 # str[8] = s 18 # str[9] = # 这里的空格也是字符串的一个字符 19 # str[10] = a 20 # str[11] = # 这里的空格也是字符串的一个字符 21 # str[12] = g 22 # str[13] = o 23 # str[14] = o 24 # str[15] = d 25 # str[16] = # 这里的空格也是字符串的一个字符 26 # str[17] = m 27 # str[18] = a 28 # str[19] = n
举例4:把一句话循环打印3遍,最终用else:输出一句话来。
1 # 举例4 2 # while语句的第二种形式 3 a = 1 4 while a <= 3: 5 print("Thomas is a good man") 6 a += 1 7 else: 8 print("very very good")
小结:在while循环控制语句中,一定要注意计数器的叠加情况。这个是控制while循环语句的重中之重。
第二部分:for 循环控制语句
存在形式如下:
(1) for 变量名 in 集合: # 集合可以是range,也可以是一个列表
语句
(2) for 变量名 in 集合:
语句
else:
语句 # 只有上面的for循环正常执行完毕,执行下面的else:语句。
解释如下:
首先,for循环也是存在两种形式,和while循环一样,最后的else:也是for循环正常执行完毕,执行下面的else:语句。不同点是:for 循环是通过一个变量名在一个集合里面去按照顺序的遍历一遍,遍历结束后这个for 循环体也就结束了。可以理解为:按照顺序取集合中的每一个元素,赋值给变量(这里看明白了,赋值给变量的意思是这个变量的值如果集合没有遍历完毕,一致按照顺序去赋值给变量进行判断,然后复制给变量进行判断,这个赋值的过程,其实我们前面接触到的print遍历一组数,字符,元组等,其实变量的值是处于不断赋值的过程,所以才能让print去打印。)如此循环往复。直到取完这个集合中的元素截止调出循环。
其次,这里我们看到用到前面所说的range(开始,结束,步长(默认为1)函数,另外后面和这个集合也可以用一个列表[1,2,3,4...]来表示。这就好像我去篮子里面拿鸡蛋,知道拿出最后一个鸡蛋for循环语句也就结束了。
最后,这里用到了前面说到的成员运算符in ,not in,其实还可用not,is ,is not身份运算符等。其实这里就是个亿逻辑判断。
这里我们把range函数在说一下:
函:range
语:range(self, [,start] [,end] [,step])
用:start--计数起始位置,end--计数结束位置,step--为计数的步长;如果range内为一个数值,默认表示时从0开始到这个数值,步长为1。这里的range也可以理解为列表生成器,生成数列,注意:所有的集合都是从0开始的序列(如果没有要求的话)
举例1:把前面while循环语句的1-5个数打印出来,用for循环来表示
1 # 举例1 2 # 遍历打印 3 for i in [1, 2, 3, 4, 5]: 4 print(i, end="") 5 print(" ") 6 # 输出结果:12345
举例2:遍历2-20,步长为2的结果。
1 # 举例2 2 # 遍历从2-20,步长为2的结果 3 for k in range(2, 20, 2): 4 print(k, end="") 5 print(" ", end="") 6 print("k的值是: %d" % k) 7 print(" ") 8 # 输出结果:2 4 6 8 10 12 14 16 18 k的值是: 18
举例3:遍历整个字符串。
1 # 遍历字符串 2 fruits = ['banana', 'apple', 'mango'] 3 for fruit in fruits: # 第二个实例 4 print ('当前水果 :', fruit) 5 # 输出结果: 6 # 当前水果 : banana 7 # 当前水果 : apple 8 # 当前水果 : mango
从这些例子里面可以看出,“遍历”的思路是循环结构中最长使用的方式方法,对于遍历我们前面也讲过一个函数叫enumerate函数,整个函数叫枚举函数,也就是在遍历的时候去记录现在遍历到第几个了。我们把这个函数再复习一下:
函:enumrate
语:enumrate(x, [,startNum])
用:这里的x为枚举哪一个集合,其中startNum可以不写,默认是从0开始的。如果写的话像这样:
默认:0 就从0 1 2 3 4 5 6 7...这样记录遍历到第几个了。
设置:1 就是1 2 3 4 5 6 7 8...这样记录遍历到第几个。
就是一个开始编号的意思。
举例4:枚举1-5个数。
1 # 举例4 2 # enumerate(x,[,start]) 枚举函数,start枚举开始数字 3 # 作用: 4 for index, m in enumerate([1, 2, 3, 4, 5], 1): 5 # index,m = 下标,元素,for 循环也可以用交换使赋值方式 6 print(index, m) 7 # 输出结果: 8 # 1 1 9 # 2 2 10 # 3 3 11 # 4 4 12 # 5 5
第三部分: 迭代器(Iterator)
迭代器这部分内容分可迭代对象和迭代器。其实迭代器从从思想上理解就是循环的一种简写方式。
可迭代对象:
可迭代对象:可直接作用于for循环的对象统称为可迭代对象(Iterable,表示可迭代的)
迭代器
迭代器:不带可以作用于for循环,还可以被next函数不断调用并返回一个值,直到最后跑出一个stopIteration错误表示无法继续返回下一个值。
可以被next()函数调用并不断返回下一个值的对象成为迭代器。
函:isinstance()
语:range(对象,识别类型)
用:这个函数可以识别iterable那些可以迭代,iterator那些可以作为迭代器。
from collections.abc import Iterable,Iterator
# 那些可以作为迭代对象 print(isinstance([],Iterable)) print(isinstance((),Iterable)) print(isinstance({},Iterable)) print(isinstance("",Iterable)) print(isinstance((x for x in range(10)),Iterable)) print(isinstance(1,Iterable)) # 迭代器有哪些? print(isinstance([],Iterator)) print(isinstance((),Iterator)) print(isinstance({},Iterator)) print(isinstance("",Iterator)) print(isinstance((x for x in range(10)),Iterator)) # 这是一个迭代器 print(isinstance(1,Iterator))
我们从返回值可以看出,除了1不能作为迭代对象,其他都可以作为迭代对象;但是iterator能作为迭代器的只有迭代表达式。
补充说明:
我们需要导入一个collections库才能用isinstatnce函数,但是在Python3更高级的版本中调用这个库会产生错误。因为这个库的名字已经更改了。
旧版:from collections import iterable,iterator
新版: from collections.abc import iterable,iterator # 增加了一个abc后缀,这里要特别说明。
函:iter()
语:iter(把什么内容变成可迭代内容,)
用:如果当前的内容不是要给迭代器,那么我们可以把什么内容转换为迭代器,后面内容不是唯一的用逗号进行分割。
函:next()
语:next(迭代器句柄)
用:这个函数不是可以一次一次的进行迭代。
举例说明:
# 迭代形式的使用 l = (x for x in range(5)) print(next(l)) print(next(l)) print(next(l)) print(next(l)) print(next(l)) # print(next(l)) # 报错了 # 返回0 1 2 3 4 迭代了4次 # 这里的迭代格式为x for x in range() # 使用迭代器,转换想要迭代的内容 a = iter([1,2,3,4,5]) print(next(a)) print(next(a)) print(next(a)) print(next(a)) print(next(a)) # 返回 1 2 3 4 5 迭代了5次 # 案例: endstr = "end" line = " " str1 = "" for str in iter(input,endstr): str1 = str1 + str if str == endstr: break str1 = str1 + line print("您输入的内容是:%s" %str1) # 解释:iter生成一个迭代内容(input,endstr),在这就好比一个循环内容,到最后一个循环 # endstr的时候结束,也就是说一直循环input1,input2,input3...,endstr最后一个输入 # end字符串结束 # 输出内容: # Thomas # is # a # good # man # end # 您输入的内容是:Thomas is a good man
因此我们可以看到迭代器不光可以迭代数据类型,还可以迭代一个函数,最后一个例子当中迭代了input这个函数
第三部分:生成器(generator)
生成器我们要记住一个函数叫做yeild,这个函数是相对于return这个来讲的。return这个表示函数结束并返回,yield这个表示暂停的意思。我们通过段函数来说明这个问题:
第一段:正常的return
def r(n): print("Hello,return") while n>0: print("before return") return n n -= 1 print("after return") r(3) # 返回值: # Hello,return # before return
我们可以看到碰到return整个值就反回了,不在执行。
第二段:改为yield的代码
def y(n): print("Hello,yield") while n>0: print("before yield") yield n n -= 1 print("after yield") yy = y(3) yy.__next__() # 注意:在python2,next前后是没有双划线的 yy.__next__() yy.__next__() yy.__next__() # 报错,执行到第三遍 # 返回值: # Hello,yield # before yield # before yield # after yield # before yield # after yield # StopIteration # 报错,执行到第三遍
总结:
这样这两个循环体就解释完了,总结有一下两点注意:
1. for语句中的"for 表达式 in 集合:"这句话是两句话的缩写
第一句:表达式1 = 集合中的第一个元素,表达式2 = 集合中的第一个元素 ... ...实际是一个赋值语句
第二句:当全部赋值完毕结束整个for循环语句
因此:遍历过程其实是把整个赋值后的表达式打印出来,但是这个值的位置只有一个,赋值——覆盖——赋值——覆盖——最后一个运算值。
2. 既然是表达式赋值方式,所以for循环也可用交互式赋值方式。
3. 同样for的表达式后也要加上“:”