不论使用什么编程语言,for和while循环基本都是通用的循环类型,而且我们也基本不会再用其它的循环控制结构了。
我们知道,for一般针对一个次数固定的循环,而while则是判断是否满足条件再走循环。
在很多情况下,用for和while都是可以实现需求的。当然了,在一般使用中,大家往往更偏爱for一些,因为循环变量可以不用自己操纵。
但也许正因为如此,一些新手,比如以前的我,用着用着就真以为两者只是个语法形式不同而已了。而且前段时间又犯了一次错,证明了我还是很菜。
今天我们来看看一个循环时容易踩的坑,借此来对比两者的不同。
请看如下例子:
对一个列表:
>>> a=list(range(1,11)) >>> a [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
现在要求:使用循环,去除其中的值小于5的项,即需要让它为[5,6,7,8,9,10]。
看上去是个很简单的事情哈,可以这么写嘛:
a=list(range(1,11))
for i in a: if i<5: a.remove(i) print(a)
查看运行结果:
[2, 4, 5, 6, 7, 8, 9, 10]
额...傻了。
分析一下,在代码中加入一个计数变量看看:
a=list(range(1,11)) k=0 for i in a: k+=1 if i<5: a.remove(i) print(a) print(k)
[2, 4, 5, 6, 7, 8, 9, 10]
8
原来这个“循环”竟然只走了8次...刚好是列表中2和4的那两次被漏掉了...
这提示了我们想到,对列表的删除,改变了其索引序列,导致了遍历的遗漏。
一栋房子,如果抽走了1楼,那上面的所有楼层的层级都要减1...
但如果抽走的是顶楼,下面的所有楼层却不受影响~~~
因此,如果使用反向循环,这个坑就不会踩了:([::-1]表示倒序)
a=list(range(1,11)) for i in a[::-1]: if i<5: a.remove(i) print(a)
[5, 6, 7, 8, 9, 10]
我们再来看看while,也是很容易出错的。首先我们要考虑到,如果while的判断条件是i<10,那就直接报错或死循环。因为列表a一被删除了项,长度就不再是10了,因此需要不断的重新计算列表a的长度。其次,还是刚才那个漏项的问题,一旦删除了某元素后,i的取值还得调整,否则是重蹈覆辙。
a=list(range(1,11)) i=0 while i<len(a): if a[i]<5: a.remove(a[i]) i=i-1 i=i+1 print(a)
[5, 6, 7, 8, 9, 10]
当然了,采用倒序遍历也是可以的。
a=list(range(1,11)) i=len(a)-1 while i>=0: if a[i]<5: a.remove(a[i]) i=i-1 print(a)
[5, 6, 7, 8, 9, 10]
总结一下,示例问题的坑的本质是,循环条件依赖的变量随着循环的进行发生了改变,从而影响了循环的执行。
对于一般的循环,确定次数的尽量用for,确定循环条件的尽量用while。(while的一个优势是每次循环都在重新检查条件,非常“仔细”)
对于循环条件依赖的变量随着循环的进行可能发生改变的情况,最主要的还是要意识到这一点,至于具体用什么方法,都是灵活处理吧。