for...else: 一个程序引发的陷阱

python3菜鸟教程有一段关于for循环和else搭配的代码:

for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(n, '等于', x, '*', n//x)
            break
    else:
        # 循环中没有找到元素
        print(n, ' 是质数')

这段代码的作用是在范围2-9之间查找质数,何为质数?除了1和它本身不能被其他数整除。

那么for...else是怎样的作用呢?当迭代的对象迭代完并为空时,将会执行else子句。

思路

理解这个程序最关键的地方在于,当n取2时,第二层for循环的范围是range(2, 2),range(2, 2)很有意思,在python2中它是一个[](空列表),对python3来说,它是一个可迭代对象,但它并不是一个迭代器,为什么这么说?我们可以用isinstance()判断一下:

#判断是否为可迭代对象

>>> from collections import Iterable
>>> isinstance(range(2, 2), Iterable)
True

#判断是否为迭代器

>>> from collections import Iterator>>> isinstance(range(2, 2), Iterator)
False

我们看到报错了,说明range(2, 2)不是一个迭代器,而是一个可迭代对象。

话说回来,当n取2时,可迭代对象已经为空了,这时程序根本不会再执行第二层for循环了,程序直接跳到了else语句,但我觉得2是质数这个结论,作者已经默认了,因为它没有经过程序的计算。

理解了这一层,接下来的第一层for循环取值从3到9,第二层for循环取除了1和它本身之外的值,举个例子,当n = 5时,x取值的范围是(2,5),只要这个范围内存在一个能被n整除的数,就能说明n不是质数,然后程序以一个break跳出循环体。

延伸

何为陷阱?陷阱就是在你看不到地方坑你一下,假设有如下代码:

for i in range(10):
    if i == 5:
        print 'found it! i = %s' % i
else:
    print 'not found it ...'

你期望的结果当i = 5时打印:

found it! i = 5tho

但实际上它打印了两条结果:

found it! i = 5
not found it ...

当迭代到i = 5时,打印"found it! i = 5",当迭代完可迭代对象为空时,跳到else子句,又会打印“not found it...”

 

参考

https://www.cnblogs.com/dspace/p/6622799.html      

https://www.cnblogs.com/AaronFan/p/6161159.html   

https://www.cnblogs.com/scofi/p/4902640.html          

 

posted @ 2018-04-19 23:53  cnhkzyy  阅读(435)  评论(0编辑  收藏  举报