循环使用的一个坑

不论使用什么编程语言,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的一个优势是每次循环都在重新检查条件,非常“仔细”)

对于循环条件依赖的变量随着循环的进行可能发生改变的情况,最主要的还是要意识到这一点,至于具体用什么方法,都是灵活处理吧。

猜你喜欢

转载自www.cnblogs.com/maoerbao/p/11864582.html