程序员入伙书——两种循环
- 2012年12月28日
- 发布在 infotech . on my mind
- 留下评论
其实咱们早已看到过循环了,只是当时并没有要求大家看明白。
循环,就是让程序反复执行同一段代码。利用计算机速度快,脾气好,不怕麻烦的优势(这几点,人类确实比不上),也省得人们把相似的任务反复书写几百遍。
有两种循环,一种是事先预知要循环多少次的,一种事先不知道。这两种循环,咱们在《程序在干什么?》一章里见过。那里头讲过三个例子,第一个例子是从1加到100,我们都知道要循环100次。第二个例子是九九乘法表,我们知道要重复做9行,每行做N列(N等于当前的行数)。第三个例子是猜平方根,这个就不能实现确实要循环多少次了,只隐约觉得精度好过亿分之一就可以结束。
预知循环次数、知道每次循环时要喂什么数据给程序的,叫做for循环。for的意思是:对于(for)每次循环,使用这些值……
预先不知道循环次数,只知道循环的结束条件的,叫做while循环,意思是:当(while)某条件判断为真的情况下,反复执行这段程序……
其实for循环是while的一个特例,例如那个从1加到100的,下面的两段程序,一个用for,一个用while,得到的结果是一样的:
>>> total = 0 >>> for i in range(1, 101): total += i >>> total 5050 >>> total = 0 >>> i = 1 >>> while i <= 100: total += i i += 1 >>> total 5050 >>>
所以我们先讲while。在Python里,while的用法是:
while 条件判断表达式: 做这个 做那个 东张西望
凹进去的这段程序,只要“条件判断表达式”为真(True),就会被反复执行。上面的累加例子里,只要i小于等于100,累加就会持续下去。
while太简单太直观了,没啥可说的,直接说for吧,for的用法是:
for var in (value_1, value_2, value_3, ..., value_n): 逛街 试穿衣服 讨价还价
凹进去的这段程序,会被执行N次,其中N等于for语句后头那个括号里的数值的个数。每次循环这段程序时,变量var会分别等于括号里的每个值。例如上头的累加例子,range(1, 101)产生了一个序列(1, 2, 3, 4, …, 100),于是for循环里面的total += i就被循环了100次,每次i换一个值,第一次等于1,第二次等于2,……最后一次等于100。
来,玩个好玩的。不需要看懂import math,只需要知道math.sin是求正弦,math.pi等于圆周率3.1415926…就可以了:
>>> import math >>> for i in range(51): print(' ' * round((math.sin(math.pi/25*i) + 1) * 30), '*') * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * >>>
哎呀呀,太简单了,又说完一个。不想提前结束怎么办呢?我再说说两个特殊的语句:break和continue。
大家一定注意到,那个猜平方根的程序里,while后面接的不是普通的条件判断表达式,而是True。来,咱们把代码再放到这儿看一下:
print('Please input a number: ', end = '') n = abs(float(input())) high = max(1, n) low = 0 while True: result = (high + low) / 2 if abs(result * result - n) < n * 1E-8: break if result * result > n: high = result else: low = result print('Square root of %g is %g' % (n, result))
理论上说,这个循环会永远执行下去,行话叫“死循环”。死循环是程序员常犯的错误之一,当然,故意做成的死循环,也是有的。咱们面前这台计算机,就是在不停地等咱们移动、点击鼠标,敲打键盘……并对每个动作做响应,之后,默默回到原点继续等待。
扯远了,接着说这个平方根程序。大家也看到了,这个程序并未陷入死循环,只跑了二十几遍就退出来了。它是从哪儿退出的呢?细细一瞧就看出端倪了,有一个语句叫做break。
break的意思是,立刻跳出眼前所在的这层循环,程序转向紧跟这个while块的下一句(这个例子里,是执行print)。注意,只跳出一层:如果循环是被嵌套在一个更大的循环里的,break不会跳出更大的那层循环。
再说continue,有时我们需要让程序逐个扫描用户的输入内容,滤掉垃圾信息,只选出有用的部分做处理。“忽略”什么东西的操作一定比“处理”什么东西的操作要简单,我们直观地想这个程序,大约就是这样写的:
while 松子还没嗑完: 取一个松子 if 松子 not 空的 and 有开口 and not 发霉: 把它放在牙槽上 咬 把指甲嵌到缝里 向两边掰开 把壳扔掉 把松子吃掉 else: 把松子扔掉
上头这个思路是对的,只是你看,if块被缩进去两次,如果嵌套层数很多,缩进的空格就和一行差不多宽了,程序很难读的。另外,大家看到if,总觉得心乱如麻的,怕还有个else在后头等着。为了给自己一种“这个数据纯属垃圾,果断丢弃!下一个!”的干练态度,continue语句就上场了。continue的意思是,忽略此循环体尚未被执行到的部分,果断回到循环的起点,准备下一次循环。刚才的这个代码就可以被写成下面的样子。
while 松子还没嗑完: 取一个松子 if 松子 空的 or not 开口 or 发霉了: 把松子扔掉 continue # 下一个! 把它放在牙槽上 咬 把指甲嵌到缝里 向两边掰开 把壳扔掉 把松子吃掉
再强调一次:虽然都是“忽略掉循环体的剩余部分”,break是跳出整个循环体,continue是回到起点准备下一次循环。
break和continue对于while和for都适用。
25是对正弦曲线取样的个数。采25个点来画这条曲线,你可以改变一下这个数字看看。
30是把曲线放大的系数。正弦曲线的取值是-1到1之间,所以我要把这条线抻得宽一些。
25和30是怎么选出来的?
加了一段看它出来的是什么,其实中间那个sin不是很懂
>>> for i in range(51):
print(round((math.sin(math.pi/25*i) + 1) * 30))
print(‘ ‘ * round((math.sin(math.pi/25*i) + 1) * 30), ‘*’)
吃松籽就是我的真实写照